PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/utxo-lib/dist/src/bitgo
Просмотр файла: UtxoPsbt.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UtxoPsbt = void 0;
const assert_1 = require("assert");
const bip174_1 = require("bip174");
const utils_1 = require("bip174/src/lib/utils");
const bufferutils_1 = require("bitcoinjs-lib/src/bufferutils");
const bip32_1 = require("bip32");
const bs58check = require("bs58check");
const proprietaryKeyVal_1 = require("bip174/src/lib/proprietaryKeyVal");
const __1 = require("..");
const UtxoTransaction_1 = require("./UtxoTransaction");
const Unspent_1 = require("./Unspent");
const scriptTypes_1 = require("./psbt/scriptTypes");
const fromHalfSigned_1 = require("./psbt/fromHalfSigned");
const outputScripts_1 = require("./outputScripts");
const parseInput_1 = require("./parseInput");
const Musig2_1 = require("./Musig2");
const types_1 = require("./types");
const taproot_1 = require("../taproot");
const PsbtUtil_1 = require("./PsbtUtil");
function defaultSighashTypes() {
return [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL];
}
function addForkIdToSighashesIfNeeded(network, sighashTypes) {
switch ((0, __1.getMainnet)(network)) {
case __1.networks.bitcoincash:
case __1.networks.bitcoinsv:
case __1.networks.bitcoingold:
case __1.networks.ecash:
return [...sighashTypes, ...sighashTypes.map((s) => s | UtxoTransaction_1.UtxoTransaction.SIGHASH_FORKID)];
default:
return sighashTypes;
}
}
function toSignatureParams(network, v) {
if (Array.isArray(v))
return toSignatureParams(network, { sighashTypes: v });
const defaultSignatureParams = { deterministic: false, sighashTypes: defaultSighashTypes() };
const ret = { ...defaultSignatureParams, ...v };
ret.sighashTypes = addForkIdToSighashesIfNeeded(network, ret.sighashTypes);
return ret;
}
/**
* @param a
* @param b
* @returns true if the two public keys are equal ignoring the y coordinate.
*/
function equalPublicKeyIgnoreY(a, b) {
return (0, outputScripts_1.toXOnlyPublicKey)(a).equals((0, outputScripts_1.toXOnlyPublicKey)(b));
}
// TODO: upstream does `checkInputsForPartialSigs` before doing things like
// `setVersion`. Our inputs could have tapscriptsigs (or in future tapkeysigs)
// and not fail that check. Do we want to do anything about that?
class UtxoPsbt extends __1.Psbt {
constructor() {
super(...arguments);
this.nonceStore = new Musig2_1.Musig2NonceStore();
}
static transactionFromBuffer(buffer, network) {
return UtxoTransaction_1.UtxoTransaction.fromBuffer(buffer, false, 'bigint', network);
}
static createPsbt(opts, data) {
return new UtxoPsbt(opts, data || new bip174_1.Psbt(new __1.PsbtTransaction({ tx: new UtxoTransaction_1.UtxoTransaction(opts.network) })));
}
static fromBuffer(buffer, opts) {
const transactionFromBuffer = (buffer) => {
const tx = this.transactionFromBuffer(buffer, opts.network);
return new __1.PsbtTransaction({ tx });
};
const psbtBase = bip174_1.Psbt.fromBuffer(buffer, transactionFromBuffer, {
bip32PathsAbsolute: opts.bip32PathsAbsolute,
});
const psbt = this.createPsbt(opts, psbtBase);
// Upstream checks for duplicate inputs here, but it seems to be of dubious value.
return psbt;
}
static fromHex(data, opts) {
return this.fromBuffer(Buffer.from(data, 'hex'), opts);
}
/**
* @param parent - Parent key. Matched with `bip32Derivations` using `fingerprint` property.
* @param bip32Derivations - possible derivations for input or output
* @param ignoreY - when true, ignore the y coordinate when matching public keys
* @return derived bip32 node if matching derivation is found, undefined if none is found
* @throws Error if more than one match is found
*/
static deriveKeyPair(parent, bip32Derivations, { ignoreY }) {
const matchingDerivations = bip32Derivations.filter((bipDv) => {
return bipDv.masterFingerprint.equals(parent.fingerprint);
});
if (!matchingDerivations.length) {
// No fingerprint match
return undefined;
}
if (matchingDerivations.length !== 1) {
throw new Error(`more than one matching derivation for fingerprint ${parent.fingerprint.toString('hex')}: ${matchingDerivations.length}`);
}
const [derivation] = matchingDerivations;
const node = parent.derivePath(derivation.path);
if (!node.publicKey.equals(derivation.pubkey)) {
if (!ignoreY || !equalPublicKeyIgnoreY(node.publicKey, derivation.pubkey)) {
throw new Error('pubkey did not match bip32Derivation');
}
}
return node;
}
static deriveKeyPairForInput(bip32, input) {
return input.tapBip32Derivation?.length
? UtxoPsbt.deriveKeyPair(bip32, input.tapBip32Derivation, { ignoreY: true })?.publicKey
: input.bip32Derivation?.length
? UtxoPsbt.deriveKeyPair(bip32, input.bip32Derivation, { ignoreY: false })?.publicKey
: bip32?.publicKey;
}
get network() {
return this.tx.network;
}
toHex() {
return this.toBuffer().toString('hex');
}
/**
* It is expensive to attempt to compute every output address using psbt.txOutputs[outputIndex]
* to then just get the script. Here, we are doing the same thing as what txOutputs() does in
* bitcoinjs-lib, but without iterating over each output.
* @param outputIndex
* @returns output script at the given index
*/
getOutputScript(outputIndex) {
return this.__CACHE.__TX.outs[outputIndex].script;
}
getNonWitnessPreviousTxids() {
const txInputs = this.txInputs; // These are somewhat costly to extract
const txidSet = new Set();
this.data.inputs.forEach((input, index) => {
if (!input.witnessUtxo) {
throw new Error('Must have witness UTXO for all inputs');
}
if (!(0, scriptTypes_1.isSegwit)(input.witnessUtxo.script, input.redeemScript)) {
txidSet.add((0, Unspent_1.getOutputIdForInput)(txInputs[index]).txid);
}
});
return [...txidSet];
}
addNonWitnessUtxos(txBufs) {
const txInputs = this.txInputs; // These are somewhat costly to extract
this.data.inputs.forEach((input, index) => {
if (!input.witnessUtxo) {
throw new Error('Must have witness UTXO for all inputs');
}
if (!(0, scriptTypes_1.isSegwit)(input.witnessUtxo.script, input.redeemScript)) {
const { txid } = (0, Unspent_1.getOutputIdForInput)(txInputs[index]);
if (txBufs[txid] === undefined) {
throw new Error('Not all required previous transactions provided');
}
this.updateInput(index, { nonWitnessUtxo: txBufs[txid] });
}
});
return this;
}
static fromTransaction(transaction, prevOutputs) {
if (prevOutputs.length !== transaction.ins.length) {
throw new Error(`Transaction has ${transaction.ins.length} inputs, but ${prevOutputs.length} previous outputs provided`);
}
const clonedTransaction = transaction.clone();
const updates = (0, fromHalfSigned_1.unsign)(clonedTransaction, prevOutputs);
const psbtBase = new bip174_1.Psbt(new __1.PsbtTransaction({ tx: clonedTransaction }));
clonedTransaction.ins.forEach(() => psbtBase.inputs.push({ unknownKeyVals: [] }));
clonedTransaction.outs.forEach(() => psbtBase.outputs.push({ unknownKeyVals: [] }));
const psbt = this.createPsbt({ network: transaction.network }, psbtBase);
updates.forEach((update, index) => {
psbt.updateInput(index, update);
psbt.updateInput(index, { witnessUtxo: { script: prevOutputs[index].script, value: prevOutputs[index].value } });
});
return psbt;
}
getUnsignedTx() {
return this.tx.clone();
}
static newTransaction(network) {
return new UtxoTransaction_1.UtxoTransaction(network);
}
get tx() {
return this.data.globalMap.unsignedTx.tx;
}
checkForSignatures(propName) {
this.data.inputs.forEach((input) => {
if (input.tapScriptSig?.length || input.tapKeySig || input.partialSig?.length) {
throw new Error(`Cannot modify ${propName ?? 'transaction'} - signatures exist.`);
}
});
}
/**
* @returns true if the input at inputIndex is a taproot key path.
* Checks for presence of minimum required key path input fields and absence of any script path only input fields.
*/
isTaprootKeyPathInput(inputIndex) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
return (!!input.tapInternalKey &&
!!input.tapMerkleRoot &&
!(input.tapLeafScript?.length ||
input.tapScriptSig?.length ||
input.tapBip32Derivation?.some((v) => v.leafHashes.length)));
}
/**
* @returns true if the input at inputIndex is a taproot script path.
* Checks for presence of minimum required script path input fields and absence of any key path only input fields.
*/
isTaprootScriptPathInput(inputIndex) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
return (!!input.tapLeafScript?.length &&
!(this.getProprietaryKeyVals(inputIndex, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTICIPANT_PUB_KEYS,
}).length ||
this.getProprietaryKeyVals(inputIndex, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PUB_NONCE,
}).length ||
this.getProprietaryKeyVals(inputIndex, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG,
}).length));
}
/**
* @returns true if the input at inputIndex is a taproot
*/
isTaprootInput(inputIndex) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
const isP2TR = (script) => {
try {
(0, taproot_1.getTaprootOutputKey)(script);
return true;
}
catch (e) {
return false;
}
};
return !!(input.tapInternalKey ||
input.tapMerkleRoot ||
input.tapLeafScript?.length ||
input.tapBip32Derivation?.length ||
input.tapScriptSig?.length ||
this.getProprietaryKeyVals(inputIndex, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTICIPANT_PUB_KEYS,
}).length ||
this.getProprietaryKeyVals(inputIndex, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PUB_NONCE,
}).length ||
this.getProprietaryKeyVals(inputIndex, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG,
}).length ||
(input.witnessUtxo && isP2TR(input.witnessUtxo.script)));
}
isMultisigTaprootScript(script) {
try {
(0, parseInput_1.parsePubScript2Of3)(script, 'taprootScriptPathSpend');
return true;
}
catch (e) {
return false;
}
}
/**
* Mostly copied from bitcoinjs-lib/ts_src/psbt.ts
*/
finalizeAllInputs() {
(0, utils_1.checkForInput)(this.data.inputs, 0); // making sure we have at least one
this.data.inputs.map((input, idx) => {
if (input.tapLeafScript?.length) {
return this.isMultisigTaprootScript(input.tapLeafScript[0].script)
? this.finalizeTaprootInput(idx)
: this.finalizeTapInputWithSingleLeafScriptAndSignature(idx);
}
else if (this.isTaprootKeyPathInput(idx)) {
return this.finalizeTaprootMusig2Input(idx);
}
return this.finalizeInput(idx);
});
return this;
}
finalizeTaprootInput(inputIndex) {
const sanitizeSignature = (sig) => {
const sighashType = sig.length === 64 ? __1.Transaction.SIGHASH_DEFAULT : sig.readUInt8(sig.length - 1);
const inputSighashType = input.sighashType === undefined ? __1.Transaction.SIGHASH_DEFAULT : input.sighashType;
(0, assert_1.ok)(sighashType === inputSighashType, 'signature sighash does not match input sighash type');
// TODO BTC-663 This should be fixed in platform. This is just a workaround fix.
return sighashType === __1.Transaction.SIGHASH_DEFAULT && sig.length === 65 ? sig.slice(0, 64) : sig;
};
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
// witness = control-block script first-sig second-sig
if (input.tapLeafScript?.length !== 1) {
throw new Error('Only one leaf script supported for finalizing');
}
const { controlBlock, script } = input.tapLeafScript[0];
const witness = [script, controlBlock];
const [pubkey1, pubkey2] = (0, parseInput_1.parsePubScript2Of3)(script, 'taprootScriptPathSpend').publicKeys;
for (const pk of [pubkey1, pubkey2]) {
const sig = input.tapScriptSig?.find(({ pubkey }) => equalPublicKeyIgnoreY(pk, pubkey));
if (!sig) {
throw new Error('Could not find signatures in Script Sig.');
}
witness.unshift(sanitizeSignature(sig.signature));
}
const witnessLength = witness.reduce((s, b) => s + b.length + bufferutils_1.varuint.encodingLength(b.length), 1);
const bufferWriter = bufferutils_1.BufferWriter.withCapacity(witnessLength);
bufferWriter.writeVector(witness);
const finalScriptWitness = bufferWriter.end();
this.data.updateInput(inputIndex, { finalScriptWitness });
this.data.clearFinalizedInput(inputIndex);
return this;
}
/**
* Finalizes a taproot musig2 input by aggregating all partial sigs.
* IMPORTANT: Always call validate* function before finalizing.
*/
finalizeTaprootMusig2Input(inputIndex) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
const partialSigs = (0, Musig2_1.parsePsbtMusig2PartialSigs)(input);
if (partialSigs?.length !== 2) {
throw new Error(`invalid number of partial signatures ${partialSigs ? partialSigs.length : 0} to finalize`);
}
const { partialSigs: pSigs, sigHashType } = (0, Musig2_1.getSigHashTypeFromSigs)(partialSigs);
const { sessionKey } = this.getMusig2SessionKey(inputIndex, sigHashType);
const aggSig = (0, Musig2_1.musig2AggregateSigs)(pSigs.map((pSig) => pSig.partialSig), sessionKey);
const sig = sigHashType === __1.Transaction.SIGHASH_DEFAULT ? aggSig : Buffer.concat([aggSig, Buffer.of(sigHashType)]);
// single signature with 64/65 bytes size is script witness for key path spend
const bufferWriter = bufferutils_1.BufferWriter.withCapacity(1 + bufferutils_1.varuint.encodingLength(sig.length) + sig.length);
bufferWriter.writeVector([sig]);
const finalScriptWitness = bufferWriter.end();
this.data.updateInput(inputIndex, { finalScriptWitness });
this.data.clearFinalizedInput(inputIndex);
// deleting only BitGo proprietary key values.
this.deleteProprietaryKeyVals(inputIndex, { identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER });
return this;
}
finalizeTapInputWithSingleLeafScriptAndSignature(inputIndex) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if (input.tapLeafScript?.length !== 1) {
throw new Error('Only one leaf script supported for finalizing');
}
if (input.tapScriptSig?.length !== 1) {
throw new Error('Could not find signatures in Script Sig.');
}
const { controlBlock, script } = input.tapLeafScript[0];
const witness = [input.tapScriptSig[0].signature, script, controlBlock];
const witnessLength = witness.reduce((s, b) => s + b.length + bufferutils_1.varuint.encodingLength(b.length), 1);
const bufferWriter = bufferutils_1.BufferWriter.withCapacity(witnessLength);
bufferWriter.writeVector(witness);
const finalScriptWitness = bufferWriter.end();
this.data.updateInput(inputIndex, { finalScriptWitness });
this.data.clearFinalizedInput(inputIndex);
return this;
}
/**
* Mostly copied from bitcoinjs-lib/ts_src/psbt.ts
*
* Unlike the function it overrides, this does not take a validator. In BitGo
* context, we know how we want to validate so we just hard code the right
* validator.
*/
validateSignaturesOfAllInputs() {
(0, utils_1.checkForInput)(this.data.inputs, 0); // making sure we have at least one
const results = this.data.inputs.map((input, idx) => {
return this.validateSignaturesOfInputCommon(idx);
});
return results.reduce((final, res) => res && final, true);
}
/**
* @returns true iff any matching valid signature is found for a derived pub key from given HD key pair.
*/
validateSignaturesOfInputHD(inputIndex, hdKeyPair) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
const pubKey = UtxoPsbt.deriveKeyPairForInput(hdKeyPair, input);
if (!pubKey) {
throw new Error('can not derive from HD key pair');
}
return this.validateSignaturesOfInputCommon(inputIndex, pubKey);
}
/**
* @returns true iff any valid signature(s) are found from bip32 data of PSBT or for given pub key.
*/
validateSignaturesOfInputCommon(inputIndex, pubkey) {
try {
if (this.isTaprootScriptPathInput(inputIndex)) {
return this.validateTaprootSignaturesOfInput(inputIndex, pubkey);
}
else if (this.isTaprootKeyPathInput(inputIndex)) {
return this.validateTaprootMusig2SignaturesOfInput(inputIndex, pubkey);
}
return this.validateSignaturesOfInput(inputIndex, (p, m, s) => __1.ecc.verify(m, p, s, true), pubkey);
}
catch (err) {
// Not an elegant solution. Might need upstream changes like custom error types.
if (err.message === 'No signatures for this pubkey') {
return false;
}
throw err;
}
}
getMusig2SessionKey(inputIndex, sigHashType) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if (!input.tapInternalKey || !input.tapMerkleRoot) {
throw new Error('both tapInternalKey and tapMerkleRoot are required');
}
const participants = this.getMusig2Participants(inputIndex, input.tapInternalKey, input.tapMerkleRoot);
const nonces = this.getMusig2Nonces(inputIndex, participants);
const { hash } = this.getTaprootHashForSig(inputIndex, [sigHashType]);
const sessionKey = (0, Musig2_1.createMusig2SigningSession)({
pubNonces: [nonces[0].pubNonce, nonces[1].pubNonce],
pubKeys: participants.participantPubKeys,
txHash: hash,
internalPubKey: input.tapInternalKey,
tapTreeRoot: input.tapMerkleRoot,
});
return { participants, nonces, hash, sessionKey };
}
/**
* @returns true for following cases.
* If valid musig2 partial signatures exists for both 2 keys, it will also verify aggregated sig
* for aggregated tweaked key (output key), otherwise only verifies partial sig.
* If pubkey is passed in input, it will check sig only for that pubkey,
* if no sig exits for such key, throws error.
* For invalid state of input data, it will throw errors.
*/
validateTaprootMusig2SignaturesOfInput(inputIndex, pubkey) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
const partialSigs = (0, Musig2_1.parsePsbtMusig2PartialSigs)(input);
if (!partialSigs) {
throw new Error(`No signatures to validate`);
}
let myPartialSigs = partialSigs;
if (pubkey) {
myPartialSigs = partialSigs.filter((kv) => equalPublicKeyIgnoreY(kv.participantPubKey, pubkey));
if (myPartialSigs?.length < 1) {
throw new Error('No signatures for this pubkey');
}
}
const { partialSigs: mySigs, sigHashType } = (0, Musig2_1.getSigHashTypeFromSigs)(myPartialSigs);
const { participants, nonces, hash, sessionKey } = this.getMusig2SessionKey(inputIndex, sigHashType);
const results = mySigs.map((mySig) => {
const myNonce = nonces.find((kv) => equalPublicKeyIgnoreY(kv.participantPubKey, mySig.participantPubKey));
if (!myNonce) {
throw new Error('Found no pub nonce for pubkey');
}
return (0, Musig2_1.musig2PartialSigVerify)(mySig.partialSig, mySig.participantPubKey, myNonce.pubNonce, sessionKey);
});
// For valid single sig or 1 or 2 failure sigs, no need to validate aggregated sig. So skip.
const result = results.every((res) => res);
if (!result || mySigs.length < 2) {
return result;
}
const aggSig = (0, Musig2_1.musig2AggregateSigs)(mySigs.map((mySig) => mySig.partialSig), sessionKey);
return __1.ecc.verifySchnorr(hash, participants.tapOutputKey, aggSig);
}
validateTaprootSignaturesOfInput(inputIndex, pubkey) {
const input = this.data.inputs[inputIndex];
const tapSigs = (input || {}).tapScriptSig;
if (!input || !tapSigs || tapSigs.length < 1) {
throw new Error('No signatures to validate');
}
let mySigs;
if (pubkey) {
mySigs = tapSigs.filter((sig) => equalPublicKeyIgnoreY(sig.pubkey, pubkey));
if (mySigs.length < 1) {
throw new Error('No signatures for this pubkey');
}
}
else {
mySigs = tapSigs;
}
const results = [];
(0, assert_1.ok)(input.tapLeafScript?.length === 1, `single tapLeafScript is expected. Got ${input.tapLeafScript?.length}`);
const [tapLeafScript] = input.tapLeafScript;
const pubKeys = this.isMultisigTaprootScript(tapLeafScript.script)
? (0, parseInput_1.parsePubScript2Of3)(tapLeafScript.script, 'taprootScriptPathSpend').publicKeys
: undefined;
for (const pSig of mySigs) {
const { signature, leafHash, pubkey } = pSig;
if (pubKeys) {
(0, assert_1.ok)(pubKeys.find((pk) => pubkey.equals(pk)), 'public key not found in tap leaf script');
}
let sigHashType;
let sig;
if (signature.length === 65) {
sigHashType = signature[64];
sig = signature.slice(0, 64);
}
else {
sigHashType = __1.Transaction.SIGHASH_DEFAULT;
sig = signature;
}
const { hash } = this.getTaprootHashForSig(inputIndex, [sigHashType], leafHash);
results.push(__1.ecc.verifySchnorr(hash, pubkey, sig));
}
return results.every((res) => res);
}
/**
* @param inputIndex
* @param rootNodes optional input root bip32 nodes to verify with. If it is not provided, globalXpub will be used.
* @return array of boolean values. True when corresponding index in `publicKeys` has signed the transaction.
* If no signature in the tx or no public key matching signature, the validation is considered as false.
* If rootNodes are not explicitly passed in, the return array will be unordered.
* Use getSortedRootNodes() instead if ordering is important.
*/
getSignatureValidationArray(inputIndex, { rootNodes }) {
if (!rootNodes && (!this.data.globalMap.globalXpub?.length || !(0, types_1.isTriple)(this.data.globalMap.globalXpub))) {
throw new Error('Cannot get signature validation array without 3 global xpubs');
}
const bip32s = rootNodes
? rootNodes
: this.data.globalMap.globalXpub?.map((xpub) => (0, bip32_1.BIP32Factory)(__1.ecc).fromBase58(bs58check.encode(xpub.extendedPubkey)));
if (!bip32s) {
throw new Error('either globalMap or rootNodes is required');
}
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if (!(0, PsbtUtil_1.getPsbtInputSignatureCount)(input)) {
return [false, false, false];
}
return bip32s.map((bip32) => {
const pubKey = UtxoPsbt.deriveKeyPairForInput(bip32, input);
if (!pubKey) {
return false;
}
try {
return this.validateSignaturesOfInputCommon(inputIndex, pubKey);
}
catch (err) {
// Not an elegant solution. Might need upstream changes like custom error types.
if (err.message === 'No signatures for this pubkey') {
return false;
}
throw err;
}
});
}
/**
* Mostly copied from bitcoinjs-lib/ts_src/psbt.ts
*/
signAllInputsHD(hdKeyPair, params) {
if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
throw new Error('Need HDSigner to sign input');
}
const { sighashTypes, deterministic } = toSignatureParams(this.network, params);
const results = [];
for (let i = 0; i < this.data.inputs.length; i++) {
try {
this.signInputHD(i, hdKeyPair, { sighashTypes, deterministic });
results.push(true);
}
catch (err) {
results.push(false);
}
}
if (results.every((v) => !v)) {
throw new Error('No inputs were signed');
}
return this;
}
/**
* Mostly copied from bitcoinjs-lib/ts_src/psbt.ts:signInputHD
*/
signTaprootInputHD(inputIndex, hdKeyPair, { sighashTypes = [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL], deterministic = false } = {}) {
if (!this.isTaprootInput(inputIndex)) {
throw new Error('not a taproot input');
}
if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
throw new Error('Need HDSigner to sign input');
}
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if (!input.tapBip32Derivation || input.tapBip32Derivation.length === 0) {
throw new Error('Need tapBip32Derivation to sign Taproot with HD');
}
const myDerivations = input.tapBip32Derivation
.map((bipDv) => {
if (bipDv.masterFingerprint.equals(hdKeyPair.fingerprint)) {
return bipDv;
}
})
.filter((v) => !!v);
if (myDerivations.length === 0) {
throw new Error('Need one tapBip32Derivation masterFingerprint to match the HDSigner fingerprint');
}
function getDerivedNode(bipDv) {
const node = hdKeyPair.derivePath(bipDv.path);
if (!equalPublicKeyIgnoreY(bipDv.pubkey, node.publicKey)) {
throw new Error('pubkey did not match tapBip32Derivation');
}
return node;
}
if (input.tapLeafScript?.length) {
const signers = myDerivations.map((bipDv) => {
const signer = getDerivedNode(bipDv);
if (!('signSchnorr' in signer)) {
throw new Error('signSchnorr function is required to sign p2tr');
}
return { signer, leafHashes: bipDv.leafHashes };
});
signers.forEach(({ signer, leafHashes }) => this.signTaprootInput(inputIndex, signer, leafHashes, sighashTypes));
}
else if (input.tapInternalKey?.length) {
const signers = myDerivations.map((bipDv) => {
const signer = getDerivedNode(bipDv);
if (!('privateKey' in signer) || !signer.privateKey) {
throw new Error('privateKey is required to sign p2tr musig2');
}
return signer;
});
signers.forEach((signer) => this.signTaprootMusig2Input(inputIndex, signer, { sighashTypes, deterministic }));
}
return this;
}
signInput(inputIndex, keyPair, sighashTypes) {
const { sighashTypes: sighashForNetwork } = toSignatureParams(this.network, sighashTypes);
return super.signInput(inputIndex, keyPair, sighashForNetwork);
}
signInputHD(inputIndex, hdKeyPair, params) {
const { sighashTypes, deterministic } = toSignatureParams(this.network, params);
if (this.isTaprootInput(inputIndex)) {
return this.signTaprootInputHD(inputIndex, hdKeyPair, { sighashTypes, deterministic });
}
else {
return super.signInputHD(inputIndex, hdKeyPair, sighashTypes);
}
}
getMusig2Participants(inputIndex, tapInternalKey, tapMerkleRoot) {
const participantsKeyValData = (0, Musig2_1.parsePsbtMusig2Participants)(this.data.inputs[inputIndex]);
if (!participantsKeyValData) {
throw new Error(`Found 0 matching participant key value instead of 1`);
}
(0, Musig2_1.assertPsbtMusig2Participants)(participantsKeyValData, tapInternalKey, tapMerkleRoot);
return participantsKeyValData;
}
getMusig2Nonces(inputIndex, participantsKeyValData) {
const noncesKeyValsData = (0, Musig2_1.parsePsbtMusig2Nonces)(this.data.inputs[inputIndex]);
if (!noncesKeyValsData || !(0, types_1.isTuple)(noncesKeyValsData)) {
throw new Error(`Found ${noncesKeyValsData?.length ? noncesKeyValsData.length : 0} matching nonce key value instead of 2`);
}
(0, Musig2_1.assertPsbtMusig2Nonces)(noncesKeyValsData, participantsKeyValData);
return noncesKeyValsData;
}
/**
* Signs p2tr musig2 key path input with 2 aggregated keys.
*
* Note: Only can sign deterministically as the cosigner
* @param inputIndex
* @param signer - XY public key and private key are required
* @param sighashTypes
* @param deterministic If true, sign the musig input deterministically
*/
signTaprootMusig2Input(inputIndex, signer, { sighashTypes = [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL], deterministic = false } = {}) {
if (!this.isTaprootKeyPathInput(inputIndex)) {
throw new Error('not a taproot musig2 input');
}
const input = this.data.inputs[inputIndex];
if (!input.tapInternalKey || !input.tapMerkleRoot) {
throw new Error('missing required input data');
}
// Retrieve and check that we have two participant nonces
const participants = this.getMusig2Participants(inputIndex, input.tapInternalKey, input.tapMerkleRoot);
const { tapOutputKey, participantPubKeys } = participants;
const signerPubKey = participantPubKeys.find((pubKey) => equalPublicKeyIgnoreY(pubKey, signer.publicKey));
if (!signerPubKey) {
throw new Error('signer pub key should match one of participant pub keys');
}
const nonces = this.getMusig2Nonces(inputIndex, participants);
const { hash, sighashType } = this.getTaprootHashForSig(inputIndex, sighashTypes);
let partialSig;
if (deterministic) {
if (!equalPublicKeyIgnoreY(signerPubKey, participantPubKeys[1])) {
throw new Error('can only add a deterministic signature on the cosigner');
}
const firstSignerNonce = nonces.find((n) => equalPublicKeyIgnoreY(n.participantPubKey, participantPubKeys[0]));
if (!firstSignerNonce) {
throw new Error('could not find the user nonce');
}
partialSig = (0, Musig2_1.musig2DeterministicSign)({
privateKey: signer.privateKey,
otherNonce: firstSignerNonce.pubNonce,
publicKeys: participantPubKeys,
internalPubKey: input.tapInternalKey,
tapTreeRoot: input.tapMerkleRoot,
hash,
}).sig;
}
else {
const sessionKey = (0, Musig2_1.createMusig2SigningSession)({
pubNonces: [nonces[0].pubNonce, nonces[1].pubNonce],
pubKeys: participantPubKeys,
txHash: hash,
internalPubKey: input.tapInternalKey,
tapTreeRoot: input.tapMerkleRoot,
});
const signerNonce = nonces.find((kv) => equalPublicKeyIgnoreY(kv.participantPubKey, signerPubKey));
if (!signerNonce) {
throw new Error('pubNonce is missing. retry signing process');
}
partialSig = (0, Musig2_1.musig2PartialSign)(signer.privateKey, signerNonce.pubNonce, sessionKey, this.nonceStore);
}
if (sighashType !== __1.Transaction.SIGHASH_DEFAULT) {
partialSig = Buffer.concat([partialSig, Buffer.of(sighashType)]);
}
const sig = (0, Musig2_1.encodePsbtMusig2PartialSig)({
participantPubKey: signerPubKey,
tapOutputKey,
partialSig: partialSig,
});
this.addProprietaryKeyValToInput(inputIndex, sig);
return this;
}
signTaprootInput(inputIndex, signer, leafHashes, sighashTypes = [__1.Transaction.SIGHASH_DEFAULT, __1.Transaction.SIGHASH_ALL]) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
// Figure out if this is script path or not, if not, tweak the private key
if (!input.tapLeafScript?.length) {
throw new Error('tapLeafScript is required for p2tr script path');
}
const pubkey = (0, outputScripts_1.toXOnlyPublicKey)(signer.publicKey);
if (input.tapLeafScript.length !== 1) {
throw new Error('Only one leaf script supported for signing');
}
const [tapLeafScript] = input.tapLeafScript;
if (this.isMultisigTaprootScript(tapLeafScript.script)) {
const pubKeys = (0, parseInput_1.parsePubScript2Of3)(tapLeafScript.script, 'taprootScriptPathSpend').publicKeys;
(0, assert_1.ok)(pubKeys.find((pk) => pubkey.equals(pk)), 'public key not found in tap leaf script');
}
const parsedControlBlock = __1.taproot.parseControlBlock(__1.ecc, tapLeafScript.controlBlock);
const { leafVersion } = parsedControlBlock;
if (leafVersion !== tapLeafScript.leafVersion) {
throw new Error('Tap script leaf version mismatch with control block');
}
const leafHash = __1.taproot.getTapleafHash(__1.ecc, parsedControlBlock, tapLeafScript.script);
if (!leafHashes.find((l) => l.equals(leafHash))) {
throw new Error(`Signer cannot sign for leaf hash ${leafHash.toString('hex')}`);
}
const { hash, sighashType } = this.getTaprootHashForSig(inputIndex, sighashTypes, leafHash);
let signature = signer.signSchnorr(hash);
if (sighashType !== __1.Transaction.SIGHASH_DEFAULT) {
signature = Buffer.concat([signature, Buffer.of(sighashType)]);
}
this.data.updateInput(inputIndex, {
tapScriptSig: [
{
pubkey,
signature,
leafHash,
},
],
});
return this;
}
getTaprootOutputScript(inputIndex) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if (input.tapLeafScript?.length) {
return __1.taproot.createTaprootOutputScript({
controlBlock: input.tapLeafScript[0].controlBlock,
leafScript: input.tapLeafScript[0].script,
});
}
else if (input.tapInternalKey && input.tapMerkleRoot) {
return __1.taproot.createTaprootOutputScript({
internalPubKey: input.tapInternalKey,
taptreeRoot: input.tapMerkleRoot,
});
}
throw new Error('not a taproot input');
}
getTaprootHashForSig(inputIndex, sighashTypes, leafHash) {
if (!this.isTaprootInput(inputIndex)) {
throw new Error('not a taproot input');
}
const sighashType = this.data.inputs[inputIndex].sighashType || __1.Transaction.SIGHASH_DEFAULT;
if (sighashTypes && sighashTypes.indexOf(sighashType) < 0) {
throw new Error(`Sighash type is not allowed. Retry the sign method passing the ` +
`sighashTypes array of whitelisted types. Sighash type: ${sighashType}`);
}
const txInputs = this.txInputs; // These are somewhat costly to extract
const prevoutScripts = [];
const prevoutValues = [];
this.data.inputs.forEach((input, i) => {
let prevout;
if (input.nonWitnessUtxo) {
// TODO: This could be costly, either cache it here, or find a way to share with super
const nonWitnessUtxoTx = this.constructor.transactionFromBuffer(input.nonWitnessUtxo, this.tx.network);
const prevoutHash = txInputs[i].hash;
const utxoHash = nonWitnessUtxoTx.getHash();
// If a non-witness UTXO is provided, its hash must match the hash specified in the prevout
if (!prevoutHash.equals(utxoHash)) {
throw new Error(`Non-witness UTXO hash for input #${i} doesn't match the hash specified in the prevout`);
}
const prevoutIndex = txInputs[i].index;
prevout = nonWitnessUtxoTx.outs[prevoutIndex];
}
else if (input.witnessUtxo) {
prevout = input.witnessUtxo;
}
else {
throw new Error('Need a Utxo input item for signing');
}
prevoutScripts.push(prevout.script);
prevoutValues.push(prevout.value);
});
const outputScript = this.getTaprootOutputScript(inputIndex);
if (!outputScript.equals(prevoutScripts[inputIndex])) {
throw new Error(`Witness script for input #${inputIndex} doesn't match the scriptPubKey in the prevout`);
}
const hash = this.tx.hashForWitnessV1(inputIndex, prevoutScripts, prevoutValues, sighashType, leafHash);
return { hash, sighashType };
}
/**
* @deprecated Please use the new method addProprietaryKeyVals(psbt, entry, index, keyValueData)
*
* Adds proprietary key value pair to PSBT input.
* Default identifierEncoding is utf-8 for identifier.
*/
addProprietaryKeyValToInput(inputIndex, keyValueData) {
return this.addUnknownKeyValToInput(inputIndex, {
key: (0, proprietaryKeyVal_1.encodeProprietaryKey)(keyValueData.key),
value: keyValueData.value,
});
}
/**
* @deprecated Please use the new method addProprietaryKeyValuesToUnknownKeyValues(psbt, entry, index, keyValueData)
* or updateProprietaryKeyValuesToUnknownKeyValues(keyValueData)
*
* Adds or updates (if exists) proprietary key value pair to PSBT input.
* Default identifierEncoding is utf-8 for identifier.
*/
addOrUpdateProprietaryKeyValToInput(inputIndex, keyValueData) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
const key = (0, proprietaryKeyVal_1.encodeProprietaryKey)(keyValueData.key);
const { value } = keyValueData;
if (input.unknownKeyVals?.length) {
const ukvIndex = input.unknownKeyVals.findIndex((ukv) => ukv.key.equals(key));
if (ukvIndex > -1) {
input.unknownKeyVals[ukvIndex] = { key, value };
return this;
}
}
this.addUnknownKeyValToInput(inputIndex, {
key,
value,
});
return this;
}
/**
* @deprecated Please use getProprietaryKeyValuesFromUnknownKeyValues(psbtField, keySearch). The new method
* allows for the retrieval of either input or output proprietary key values.
*
* To search any data from proprietary key value against keydata in the inputs.
* Default identifierEncoding is utf-8 for identifier.
*/
getProprietaryKeyVals(inputIndex, keySearch) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
return (0, PsbtUtil_1.getPsbtInputProprietaryKeyVals)(input, keySearch);
}
/**
* @deprecated Please use deleteProprietaryKeyValues(type, index, keysToDelete?). The new method
* allows for the deletion of either input or output proprietary key values.
*
* To delete any data from proprietary key value in PSBT input.
* Default identifierEncoding is utf-8 for identifier.
*/
deleteProprietaryKeyVals(inputIndex, keysToDelete) {
const input = (0, utils_1.checkForInput)(this.data.inputs, inputIndex);
if (!input.unknownKeyVals?.length) {
return this;
}
if (keysToDelete && keysToDelete.subtype === undefined && Buffer.isBuffer(keysToDelete.keydata)) {
throw new Error('invalid proprietary key search filter combination. subtype is required');
}
input.unknownKeyVals = input.unknownKeyVals.filter((keyValue, i) => {
const key = (0, proprietaryKeyVal_1.decodeProprietaryKey)(keyValue.key);
return !(keysToDelete === undefined ||
(keysToDelete.identifier === key.identifier &&
(keysToDelete.subtype === undefined ||
(keysToDelete.subtype === key.subtype &&
(!Buffer.isBuffer(keysToDelete.keydata) || keysToDelete.keydata.equals(key.keydata))))));
});
return this;
}
createMusig2NonceForInput(inputIndex, keyPair, keyType, params = { deterministic: false }) {
const input = this.data.inputs[inputIndex];
if (!input.tapInternalKey) {
throw new Error('tapInternalKey is required to create nonce');
}
if (!input.tapMerkleRoot) {
throw new Error('tapMerkleRoot is required to create nonce');
}
const getDerivedKeyPair = () => {
if (!input.tapBip32Derivation?.length) {
throw new Error('tapBip32Derivation is required to create nonce');
}
const derived = UtxoPsbt.deriveKeyPair(keyPair, input.tapBip32Derivation, { ignoreY: true });
if (!derived) {
throw new Error('No bip32Derivation masterFingerprint matched the HD keyPair fingerprint');
}
return derived;
};
const derivedKeyPair = keyType === 'root' ? getDerivedKeyPair() : keyPair;
if (!derivedKeyPair.privateKey) {
throw new Error('privateKey is required to create nonce');
}
const participants = (0, Musig2_1.parsePsbtMusig2Participants)(input);
if (!participants) {
throw new Error(`Found 0 matching participant key value instead of 1`);
}
(0, Musig2_1.assertPsbtMusig2Participants)(participants, input.tapInternalKey, input.tapMerkleRoot);
const { tapOutputKey, participantPubKeys } = participants;
const participantPubKey = participantPubKeys.find((pubKey) => equalPublicKeyIgnoreY(pubKey, derivedKeyPair.publicKey));
if (!Buffer.isBuffer(participantPubKey)) {
throw new Error('participant plain pub key should match one bip32Derivation plain pub key');
}
const { hash } = this.getTaprootHashForSig(inputIndex);
let pubNonce;
if (params.deterministic) {
if (params.sessionId) {
throw new Error('Cannot add extra entropy when generating a deterministic nonce');
}
// There must be only 2 participant pubKeys if it got to this point
if (!equalPublicKeyIgnoreY(participantPubKey, participantPubKeys[1])) {
throw new Error(`Only the cosigner's nonce can be set deterministically`);
}
const nonces = (0, Musig2_1.parsePsbtMusig2Nonces)(input);
if (!nonces) {
throw new Error(`No nonces found on input #${inputIndex}`);
}
if (nonces.length > 2) {
throw new Error(`Cannot have more than 2 nonces`);
}
const firstSignerNonce = nonces.find((kv) => equalPublicKeyIgnoreY(kv.participantPubKey, participantPubKeys[0]));
if (!firstSignerNonce) {
throw new Error('signer nonce must be set if cosigner nonce is to be derived deterministically');
}
pubNonce = (0, Musig2_1.createMusig2DeterministicNonce)({
privateKey: derivedKeyPair.privateKey,
otherNonce: firstSignerNonce.pubNonce,
publicKeys: participantPubKeys,
internalPubKey: input.tapInternalKey,
tapTreeRoot: input.tapMerkleRoot,
hash,
});
}
else {
pubNonce = Buffer.from(this.nonceStore.createMusig2Nonce(derivedKeyPair.privateKey, participantPubKey, tapOutputKey, hash, params.sessionId));
}
return { tapOutputKey, participantPubKey, pubNonce };
}
setMusig2NoncesInner(keyPair, keyType, inputIndex, params = { deterministic: false }) {
if (keyPair.isNeutered()) {
throw new Error('private key is required to generate nonce');
}
if (Buffer.isBuffer(params.sessionId) && params.sessionId.length !== 32) {
throw new Error(`Invalid sessionId size ${params.sessionId.length}`);
}
const inputIndexes = inputIndex === undefined ? [...Array(this.inputCount).keys()] : [inputIndex];
inputIndexes.forEach((index) => {
if (!this.isTaprootKeyPathInput(index)) {
return;
}
const nonce = this.createMusig2NonceForInput(index, keyPair, keyType, params);
this.addOrUpdateProprietaryKeyValToInput(index, (0, Musig2_1.encodePsbtMusig2PubNonce)(nonce));
});
return this;
}
/**
* Generates and sets MuSig2 nonce to taproot key path input at inputIndex.
* If input is not a taproot key path, no action.
*
* @param inputIndex input index
* @param keyPair derived key pair
* @param sessionId Optional extra entropy. If provided it must either be a counter unique to this secret key,
* (converted to an array of 32 bytes), or 32 uniformly random bytes.
* @param deterministic If true, set the cosigner nonce deterministically
*/
setInputMusig2Nonce(inputIndex, derivedKeyPair, params = { deterministic: false }) {
return this.setMusig2NoncesInner(derivedKeyPair, 'derived', inputIndex, params);
}
/**
* Generates and sets MuSig2 nonce to taproot key path input at inputIndex.
* If input is not a taproot key path, no action.
*
* @param inputIndex input index
* @param keyPair HD root key pair
* @param sessionId Optional extra entropy. If provided it must either be a counter unique to this secret key,
* (converted to an array of 32 bytes), or 32 uniformly random bytes.
* @param deterministic If true, set the cosigner nonce deterministically
*/
setInputMusig2NonceHD(inputIndex, keyPair, params = { deterministic: false }) {
(0, utils_1.checkForInput)(this.data.inputs, inputIndex);
return this.setMusig2NoncesInner(keyPair, 'root', inputIndex, params);
}
/**
* Generates and sets MuSig2 nonce to all taproot key path inputs. Other inputs will be skipped.
*
* @param inputIndex input index
* @param keyPair derived key pair
* @param sessionId Optional extra entropy. If provided it must either be a counter unique to this secret key,
* (converted to an array of 32 bytes), or 32 uniformly random bytes.
*/
setAllInputsMusig2Nonce(keyPair, params = { deterministic: false }) {
return this.setMusig2NoncesInner(keyPair, 'derived', undefined, params);
}
/**
* Generates and sets MuSig2 nonce to all taproot key path inputs. Other inputs will be skipped.
*
* @param inputIndex input index
* @param keyPair HD root key pair
* @param sessionId Optional extra entropy. If provided it must either be a counter unique to this secret key,
* (converted to an array of 32 bytes), or 32 uniformly random bytes.
*/
setAllInputsMusig2NonceHD(keyPair, params = { deterministic: false }) {
return this.setMusig2NoncesInner(keyPair, 'root', undefined, params);
}
clone() {
return UtxoPsbt.fromBuffer(this.toBuffer(), { network: this.network });
}
extractTransaction(disableFeeCheck = true) {
const tx = super.extractTransaction(disableFeeCheck);
if (tx instanceof UtxoTransaction_1.UtxoTransaction) {
return tx;
}
throw new Error('extractTransaction did not return instace of UtxoTransaction');
}
}
exports.UtxoPsbt = UtxoPsbt;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXR4b1BzYnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYml0Z28vVXR4b1BzYnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQXNDO0FBQ3RDLG1DQUEwQztBQVExQyxnREFBcUQ7QUFDckQsK0RBQXNFO0FBRXRFLGlDQUFxRDtBQUNyRCx1Q0FBdUM7QUFDdkMsd0VBQThGO0FBRTlGLDBCQVlZO0FBQ1osdURBQW9EO0FBQ3BELHVDQUFnRDtBQUNoRCxvREFBOEM7QUFDOUMsMERBQStDO0FBQy9DLG1EQUFtRDtBQUNuRCw2Q0FBa0Q7QUFDbEQscUNBa0JrQjtBQUNsQixtQ0FBMkQ7QUFDM0Qsd0NBQWlEO0FBQ2pELHlDQUtvQjtBQWFwQixTQUFTLG1CQUFtQjtJQUMxQixPQUFPLENBQUMsZUFBVyxDQUFDLGVBQWUsRUFBRSxlQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDaEUsQ0FBQztBQUVELFNBQVMsNEJBQTRCLENBQUMsT0FBZ0IsRUFBRSxZQUFzQjtJQUM1RSxRQUFRLElBQUEsY0FBVSxFQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDNUIsS0FBSyxZQUFRLENBQUMsV0FBVyxDQUFDO1FBQzFCLEtBQUssWUFBUSxDQUFDLFNBQVMsQ0FBQztRQUN4QixLQUFLLFlBQVEsQ0FBQyxXQUFXLENBQUM7UUFDMUIsS0FBSyxZQUFRLENBQUMsS0FBSztZQUNqQixPQUFPLENBQUMsR0FBRyxZQUFZLEVBQUUsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsaUNBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQzNGO1lBQ0UsT0FBTyxZQUFZLENBQUM7SUFDeEIsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGlCQUFpQixDQUFDLE9BQWdCLEVBQUUsQ0FBdUM7SUFDbEYsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUFF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J2Fzc2VydCc7XG5pbXBvcnQgeyBQc2J0IGFzIFBzYnRCYXNlIH0gZnJvbSAnYmlwMTc0JztcbmltcG9ydCB7XG4gIEJpcDMyRGVyaXZhdGlvbixcbiAgUHNidElucHV0LFxuICBUYXBCaXAzMkRlcml2YXRpb24sXG4gIFRyYW5zYWN0aW9uIGFzIElUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb25Gcm9tQnVmZmVyLFxufSBmcm9tICdiaXAxNzQvc3JjL2xpYi9pbnRlcmZhY2VzJztcbmltcG9ydCB7IGNoZWNrRm9ySW5wdXQgfSBmcm9tICdiaXAxNzQvc3JjL2xpYi91dGlscyc7XG5pbXBvcnQgeyBCdWZmZXJXcml0ZXIsIHZhcnVpbnQgfSBmcm9tICdiaXRjb2luanMtbGliL3NyYy9idWZmZXJ1dGlscyc7XG5pbXBvcnQgeyBTZXNzaW9uS2V5IH0gZnJvbSAnQGJyYW5kb25ibGFjay9tdXNpZyc7XG5pbXBvcnQgeyBCSVAzMkZhY3RvcnksIEJJUDMySW50ZXJmYWNlIH0gZnJvbSAnYmlwMzInO1xuaW1wb3J0ICogYXMgYnM1OGNoZWNrIGZyb20gJ2JzNThjaGVjayc7XG5pbXBvcnQgeyBkZWNvZGVQcm9wcmlldGFyeUtleSwgZW5jb2RlUHJvcHJpZXRhcnlLZXkgfSBmcm9tICdiaXAxNzQvc3JjL2xpYi9wcm9wcmlldGFyeUtleVZhbCc7XG5cbmltcG9ydCB7XG4gIHRhcHJvb3QsXG4gIEhEU2lnbmVyLFxuICBTaWduZXIsXG4gIFBzYnQsXG4gIFBzYnRUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb24sXG4gIFR4T3V0cHV0LFxuICBOZXR3b3JrLFxuICBlY2MgYXMgZWNjTGliLFxuICBnZXRNYWlubmV0LFxuICBuZXR3b3Jrcyxcbn0gZnJvbSAnLi4nO1xuaW1wb3J0IHsgVXR4b1RyYW5zYWN0aW9uIH0gZnJvbSAnLi9VdHhvVHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgZ2V0T3V0cHV0SWRGb3JJbnB1dCB9IGZyb20gJy4vVW5zcGVudCc7XG5pbXBvcnQgeyBpc1NlZ3dpdCB9IGZyb20gJy4vcHNidC9zY3JpcHRUeXBlcyc7XG5pbXBvcnQgeyB1bnNpZ24gfSBmcm9tICcuL3BzYnQvZnJvbUhhbGZTaWduZWQnO1xuaW1wb3J0IHsgdG9YT25seVB1YmxpY0tleSB9IGZyb20gJy4vb3V0cHV0U2NyaXB0cyc7XG5pbXBvcnQgeyBwYXJzZVB1YlNjcmlwdDJPZjMgfSBmcm9tICcuL3BhcnNlSW5wdXQnO1xuaW1wb3J0IHtcbiAgY3JlYXRlTXVzaWcyU2lnbmluZ1Nlc3Npb24sXG4gIGVuY29kZVBzYnRNdXNpZzJQYXJ0aWFsU2lnLFxuICBlbmNvZGVQc2J0TXVzaWcyUHViTm9uY2UsXG4gIG11c2lnMlBhcnRpYWxTaWduLFxuICBwYXJzZVBzYnRNdXNpZzJOb25jZXMsXG4gIHBhcnNlUHNidE11c2lnMlBhcnRpY2lwYW50cyxcbiAgUHNidE11c2lnMlBhcnRpY2lwYW50cyxcbiAgYXNzZXJ0UHNidE11c2lnMk5vbmNlcyxcbiAgYXNzZXJ0UHNidE11c2lnMlBhcnRpY2lwYW50cyxcbiAgTXVzaWcyTm9uY2VTdG9yZSxcbiAgUHNidE11c2lnMlB1Yk5vbmNlLFxuICBwYXJzZVBzYnRNdXNpZzJQYXJ0aWFsU2lncyxcbiAgbXVzaWcyUGFydGlhbFNpZ1ZlcmlmeSxcbiAgbXVzaWcyQWdncmVnYXRlU2lncyxcbiAgZ2V0U2lnSGFzaFR5cGVGcm9tU2lncyxcbiAgbXVzaWcyRGV0ZXJtaW5pc3RpY1NpZ24sXG4gIGNyZWF0ZU11c2lnMkRldGVybWluaXN0aWNOb25jZSxcbn0gZnJvbSAnLi9NdXNpZzInO1xuaW1wb3J0IHsgaXNUcmlwbGUsIGlzVHVwbGUsIFRyaXBsZSwgVHVwbGUgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGdldFRhcHJvb3RPdXRwdXRLZXkgfSBmcm9tICcuLi90YXByb290JztcbmltcG9ydCB7XG4gIGdldFBzYnRJbnB1dFByb3ByaWV0YXJ5S2V5VmFscyxcbiAgZ2V0UHNidElucHV0U2lnbmF0dXJlQ291bnQsXG4gIFByb3ByaWV0YXJ5S2V5U3VidHlwZSxcbiAgUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSLFxufSBmcm9tICcuL1BzYnRVdGlsJztcbmltcG9ydCB7IFByb3ByaWV0YXJ5S2V5U2VhcmNoLCBQcm9wcmlldGFyeUtleVZhbHVlIH0gZnJvbSAnLi9Qcm9wcmlldGFyeUtleVZhbFV0aWxzJztcblxudHlwZSBTaWduYXR1cmVQYXJhbXMgPSB7XG4gIC8qKiBXaGVuIHRydWUsIGFuZCBhZGQgdGhlIHNlY29uZCAobGFzdCkgbm9uY2UgYW5kIHNpZ25hdHVyZSBmb3IgYSB0YXByb290IGtleVxuICAgKiBwYXRoIHNwZW5kIGRldGVybWluaXN0aWNhbGx5LiBUaHJvd3MgYW4gZXJyb3IgaWYgZG9uZSBmb3IgdGhlIGZpcnN0IG5vbmNlL3NpZ25hdHVyZVxuICAgKiBvZiBhIHRhcHJvb3Qga2V5cGF0aCBzcGVuZC4gSWdub3JlIGZvciBhbGwgb3RoZXIgaW5wdXQgdHlwZXMuXG4gICAqL1xuICBkZXRlcm1pbmlzdGljOiBib29sZWFuO1xuICAvKiogQWxsb3dlZCBzaWdoYXNoIHR5cGVzICovXG4gIHNpZ2hhc2hUeXBlczogbnVtYmVyW107XG59O1xuXG5mdW5jdGlvbiBkZWZhdWx0U2lnaGFzaFR5cGVzKCk6IG51bWJlcltdIHtcbiAgcmV0dXJuIFtUcmFuc2FjdGlvbi5TSUdIQVNIX0RFRkFVTFQsIFRyYW5zYWN0aW9uLlNJR0hBU0hfQUxMXTtcbn1cblxuZnVuY3Rpb24gYWRkRm9ya0lkVG9TaWdoYXNoZXNJZk5lZWRlZChuZXR3b3JrOiBOZXR3b3JrLCBzaWdoYXNoVHlwZXM6IG51bWJlcltdKTogbnVtYmVyW10ge1xuICBzd2l0Y2ggKGdldE1haW5uZXQobmV0d29yaykpIHtcbiAgICBjYXNlIG5ldHdvcmtzLmJpdGNvaW5jYXNoOlxuICAgIGNhc2UgbmV0d29ya3MuYml0Y29pbnN2OlxuICAgIGNhc2UgbmV0d29ya3MuYml0Y29pbmdvbGQ6XG4gICAgY2FzZSBuZXR3b3Jrcy5lY2FzaDpcbiAgICAgIHJldHVybiBbLi4uc2lnaGFzaFR5cGVzLCAuLi5zaWdoYXNoVHlwZXMubWFwKChzKSA9PiBzIHwgVXR4b1RyYW5zYWN0aW9uLlNJR0hBU0hfRk9SS0lEKV07XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBzaWdoYXNoVHlwZXM7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9TaWduYXR1cmVQYXJhbXMobmV0d29yazogTmV0d29yaywgdj86IFBhcnRpYWw8U2lnbmF0dXJlUGFyYW1zPiB8IG51bWJlcltdKTogU2lnbmF0dXJlUGFyYW1zIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkodikpIHJldHVybiB0b1NpZ25hdHVyZVBhcmFtcyhuZXR3b3JrLCB7IHNpZ2hhc2hUeXBlczogdiB9KTtcbiAgY29uc3QgZGVmYXVsdFNpZ25hdHVyZVBhcmFtcyA9IHsgZGV0ZXJtaW5pc3RpYzogZmFsc2UsIHNpZ2hhc2hUeXBlczogZGVmYXVsdFNpZ2hhc2hUeXBlcygpIH07XG4gIGNvbnN0IHJldCA9IHsgLi4uZGVmYXVsdFNpZ25hdHVyZVBhcmFtcywgLi4udiB9O1xuICByZXQuc2lnaGFzaFR5cGVzID0gYWRkRm9ya0lkVG9TaWdoYXNoZXNJZk5lZWRlZChuZXR3b3JrLCByZXQuc2lnaGFzaFR5cGVzKTtcbiAgcmV0dXJuIHJldDtcbn1cblxuLyoqXG4gKiBAcGFyYW0gYVxuICogQHBhcmFtIGJcbiAqIEByZXR1cm5zIHRydWUgaWYgdGhlIHR3byBwdWJsaWMga2V5cyBhcmUgZXF1YWwgaWdub3JpbmcgdGhlIHkgY29vcmRpbmF0ZS5cbiAqL1xuZnVuY3Rpb24gZXF1YWxQdWJsaWNLZXlJZ25vcmVZKGE6IEJ1ZmZlciwgYjogQnVmZmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiB0b1hPbmx5UHVibGljS2V5KGEpLmVxdWFscyh0b1hPbmx5UHVibGljS2V5KGIpKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIRFRhcHJvb3RTaWduZXIgZXh0ZW5kcyBIRFNpZ25lciB7XG4gIC8qKlxuICAgKiBUaGUgcGF0aCBzdHJpbmcgbXVzdCBtYXRjaCAvXm0oXFwvXFxkKyc/KSskL1xuICAgKiBleC4gbS80NCcvMCcvMCcvMS8yMyBsZXZlbHMgd2l0aCAnIG11c3QgYmUgaGFyZCBkZXJpdmF0aW9uc1xuICAgKi9cbiAgZGVyaXZlUGF0aChwYXRoOiBzdHJpbmcpOiBIRFRhcHJvb3RTaWduZXI7XG4gIC8qKlxuICAgKiBJbnB1dCBoYXNoICh0aGUgXCJtZXNzYWdlIGRpZ2VzdFwiKSBmb3IgdGhlIHNpZ25hdHVyZSBhbGdvcml0aG1cbiAgICogUmV0dXJuIGEgNjQgYnl0ZSBzaWduYXR1cmUgKDMyIGJ5dGUgciBhbmQgMzIgYnl0ZSBzIGluIHRoYXQgb3JkZXIpXG4gICAqL1xuICBzaWduU2Nobm9ycihoYXNoOiBCdWZmZXIpOiBCdWZmZXI7XG59XG5cbi8qKlxuICogSEQgc2lnbmVyIG9iamVjdCBmb3IgdGFwcm9vdCBwMnRyIG11c2lnMiBrZXkgcGF0aCBzaWduXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSERUYXByb290TXVzaWcyU2lnbmVyIGV4dGVuZHMgSERTaWduZXIge1xuICAvKipcbiAgICogTXVzaWcyIHJlcXVpcmVzIHNpZ25lcidzIDMyLWJ5dGVzIHByaXZhdGUga2V5IHRvIGJlIHBhc3NlZCB0byBpdC5cbiAgICovXG4gIHByaXZhdGVLZXk6IEJ1ZmZlcjtcblxuICAvKipcbiAgICogVGhlIHBhdGggc3RyaW5nIG11c3QgbWF0Y2ggL15tKFxcL1xcZCsnPykrJC9cbiAgICogZXguIG0vNDQnLzAnLzAnLzEvMjMgbGV2ZWxzIHdpdGggJyBtdXN0IGJlIGhhcmQgZGVyaXZhdGlvbnNcbiAgICovXG4gIGRlcml2ZVBhdGgocGF0aDogc3RyaW5nKTogSERUYXByb290TXVzaWcyU2lnbmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNjaG5vcnJTaWduZXIge1xuICBwdWJsaWNLZXk6IEJ1ZmZlcjtcbiAgc2lnblNjaG5vcnIoaGFzaDogQnVmZmVyKTogQnVmZmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE11c2lnMlNpZ25lciB7XG4gIHB1YmxpY0tleTogQnVmZmVyO1xuICBwcml2YXRlS2V5OiBCdWZmZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFwcm9vdFNpZ25lciB7XG4gIGxlYWZIYXNoZXM6IEJ1ZmZlcltdO1xuICBzaWduZXI6IFNjaG5vcnJTaWduZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHNidE9wdHMge1xuICBuZXR3b3JrOiBOZXR3b3JrO1xuICBtYXhpbXVtRmVlUmF0ZT86IG51bWJlcjsgLy8gW3NhdC9ieXRlXVxuICBiaXAzMlBhdGhzQWJzb2x1dGU/OiBib29sZWFuO1xufVxuXG4vLyBUT0RPOiB1cHN0cmVhbSBkb2VzIGBjaGVja0lucHV0c0ZvclBhcnRpYWxTaWdzYCBiZWZvcmUgZG9pbmcgdGhpbmdzIGxpa2Vcbi8vIGBzZXRWZXJzaW9uYC4gT3VyIGlucHV0cyBjb3VsZCBoYXZlIHRhcHNjcmlwdHNpZ3MgKG9yIGluIGZ1dHVyZSB0YXBrZXlzaWdzKVxuLy8gYW5kIG5vdCBmYWlsIHRoYXQgY2hlY2suIERvIHdlIHdhbnQgdG8gZG8gYW55dGhpbmcgYWJvdXQgdGhhdD9cbmV4cG9ydCBjbGFzcyBVdHhvUHNidDxUeCBleHRlbmRzIFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+ID0gVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4+IGV4dGVuZHMgUHNidCB7XG4gIHByaXZhdGUgbm9uY2VTdG9yZSA9IG5ldyBNdXNpZzJOb25jZVN0b3JlKCk7XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyB0cmFuc2FjdGlvbkZyb21CdWZmZXIoYnVmZmVyOiBCdWZmZXIsIG5ldHdvcms6IE5ldHdvcmspOiBVdHhvVHJhbnNhY3Rpb248YmlnaW50PiB7XG4gICAgcmV0dXJuIFV0eG9UcmFuc2FjdGlvbi5mcm9tQnVmZmVyPGJpZ2ludD4oYnVmZmVyLCBmYWxzZSwgJ2JpZ2ludCcsIG5ldHdvcmspO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZVBzYnQob3B0czogUHNidE9wdHMsIGRhdGE/OiBQc2J0QmFzZSk6IFV0eG9Qc2J0IHtcbiAgICByZXR1cm4gbmV3IFV0eG9Qc2J0KFxuICAgICAgb3B0cyxcbiAgICAgIGRhdGEgfHwgbmV3IFBzYnRCYXNlKG5ldyBQc2J0VHJhbnNhY3Rpb24oeyB0eDogbmV3IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+KG9wdHMubmV0d29yaykgfSkpXG4gICAgKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tQnVmZmVyKGJ1ZmZlcjogQnVmZmVyLCBvcHRzOiBQc2J0T3B0cyk6IFV0eG9Qc2J0IHtcbiAgICBjb25zdCB0cmFuc2FjdGlvbkZyb21CdWZmZXI6IFRyYW5zYWN0aW9uRnJvbUJ1ZmZlciA9IChidWZmZXI6IEJ1ZmZlcik6IElUcmFuc2FjdGlvbiA9PiB7XG4gICAgICBjb25zdCB0eCA9IHRoaXMudHJhbnNhY3Rpb25Gcm9tQnVmZmVyKGJ1ZmZlciwgb3B0cy5uZXR3b3JrKTtcbiAgICAgIHJldHVybiBuZXcgUHNidFRyYW5zYWN0aW9uKHsgdHggfSk7XG4gICAgfTtcbiAgICBjb25zdCBwc2J0QmFzZSA9IFBzYnRCYXNlLmZyb21CdWZmZXIoYnVmZmVyLCB0cmFuc2FjdGlvbkZyb21CdWZmZXIsIHtcbiAgICAgIGJpcDMyUGF0aHNBYnNvbHV0ZTogb3B0cy5iaXAzMlBhdGhzQWJzb2x1dGUsXG4gICAgfSk7XG4gICAgY29uc3QgcHNidCA9IHRoaXMuY3JlYXRlUHNidChvcHRzLCBwc2J0QmFzZSk7XG4gICAgLy8gVXBzdHJlYW0gY2hlY2tzIGZvciBkdXBsaWNhdGUgaW5wdXRzIGhlcmUsIGJ1dCBpdCBzZWVtcyB0byBiZSBvZiBkdWJpb3VzIHZhbHVlLlxuICAgIHJldHVybiBwc2J0O1xuICB9XG5cbiAgc3RhdGljIGZyb21IZXgoZGF0YTogc3RyaW5nLCBvcHRzOiBQc2J0T3B0cyk6IFV0eG9Qc2J0IHtcbiAgICByZXR1cm4gdGhpcy5mcm9tQnVmZmVyKEJ1ZmZlci5mcm9tKGRhdGEsICdoZXgnKSwgb3B0cyk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHBhcmVudCAtIFBhcmVudCBrZXkuIE1hdGNoZWQgd2l0aCBgYmlwMzJEZXJpdmF0aW9uc2AgdXNpbmcgYGZpbmdlcnByaW50YCBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIGJpcDMyRGVyaXZhdGlvbnMgLSBwb3NzaWJsZSBkZXJpdmF0aW9ucyBmb3IgaW5wdXQgb3Igb3V0cHV0XG4gICAqIEBwYXJhbSBpZ25vcmVZIC0gd2hlbiB0cnVlLCBpZ25vcmUgdGhlIHkgY29vcmRpbmF0ZSB3aGVuIG1hdGNoaW5nIHB1YmxpYyBrZXlzXG4gICAqIEByZXR1cm4gZGVyaXZlZCBiaXAzMiBub2RlIGlmIG1hdGNoaW5nIGRlcml2YXRpb24gaXMgZm91bmQsIHVuZGVmaW5lZCBpZiBub25lIGlzIGZvdW5kXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgbW9yZSB0aGFuIG9uZSBtYXRjaCBpcyBmb3VuZFxuICAgKi9cbiAgc3RhdGljIGRlcml2ZUtleVBhaXIoXG4gICAgcGFyZW50OiBCSVAzMkludGVyZmFjZSxcbiAgICBiaXAzMkRlcml2YXRpb25zOiBCaXAzMkRlcml2YXRpb25bXSxcbiAgICB7IGlnbm9yZVkgfTogeyBpZ25vcmVZOiBib29sZWFuIH1cbiAgKTogQklQMzJJbnRlcmZhY2UgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1hdGNoaW5nRGVyaXZhdGlvbnMgPSBiaXAzMkRlcml2YXRpb25zLmZpbHRlcigoYmlwRHYpID0+IHtcbiAgICAgIHJldHVybiBiaXBEdi5tYXN0ZXJGaW5nZXJwcmludC5lcXVhbHMocGFyZW50LmZpbmdlcnByaW50KTtcbiAgICB9KTtcblxuICAgIGlmICghbWF0Y2hpbmdEZXJpdmF0aW9ucy5sZW5ndGgpIHtcbiAgICAgIC8vIE5vIGZpbmdlcnByaW50IG1hdGNoXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChtYXRjaGluZ0Rlcml2YXRpb25zLmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgbW9yZSB0aGFuIG9uZSBtYXRjaGluZyBkZXJpdmF0aW9uIGZvciBmaW5nZXJwcmludCAke3BhcmVudC5maW5nZXJwcmludC50b1N0cmluZygnaGV4Jyl9OiAke1xuICAgICAgICAgIG1hdGNoaW5nRGVyaXZhdGlvbnMubGVuZ3RoXG4gICAgICAgIH1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IFtkZXJpdmF0aW9uXSA9IG1hdGNoaW5nRGVyaXZhdGlvbnM7XG4gICAgY29uc3Qgbm9kZSA9IHBhcmVudC5kZXJpdmVQYXRoKGRlcml2YXRpb24ucGF0aCk7XG5cbiAgICBpZiAoIW5vZGUucHVibGljS2V5LmVxdWFscyhkZXJpdmF0aW9uLnB1YmtleSkpIHtcbiAgICAgIGlmICghaWdub3JlWSB8fCAhZXF1YWxQdWJsaWNLZXlJZ25vcmVZKG5vZGUucHVibGljS2V5LCBkZXJpdmF0aW9uLnB1YmtleSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwdWJrZXkgZGlkIG5vdCBtYXRjaCBiaXAzMkRlcml2YXRpb24nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIHN0YXRpYyBkZXJpdmVLZXlQYWlyRm9ySW5wdXQoYmlwMzI6IEJJUDMySW50ZXJmYWNlLCBpbnB1dDogUHNidElucHV0KTogQnVmZmVyIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gaW5wdXQudGFwQmlwMzJEZXJpdmF0aW9uPy5sZW5ndGhcbiAgICAgID8gVXR4b1BzYnQuZGVyaXZlS2V5UGFpcihiaXAzMiwgaW5wdXQudGFwQmlwMzJEZXJpdmF0aW9uLCB7IGlnbm9yZVk6IHRydWUgfSk/LnB1YmxpY0tleVxuICAgICAgOiBpbnB1dC5iaXAzMkRlcml2YXRpb24/Lmxlbmd0aFxuICAgICAgPyBVdHhvUHNidC5kZXJpdmVLZXlQYWlyKGJpcDMyLCBpbnB1dC5iaXAzMkRlcml2YXRpb24sIHsgaWdub3JlWTogZmFsc2UgfSk/LnB1YmxpY0tleVxuICAgICAgOiBiaXAzMj8ucHVibGljS2V5O1xuICB9XG5cbiAgZ2V0IG5ldHdvcmsoKTogTmV0d29yayB7XG4gICAgcmV0dXJuIHRoaXMudHgubmV0d29yaztcbiAgfVxuXG4gIHRvSGV4KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMudG9CdWZmZXIoKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogSXQgaXMgZXhwZW5zaXZlIHRvIGF0dGVtcHQgdG8gY29tcHV0ZSBldmVyeSBvdXRwdXQgYWRkcmVzcyB1c2luZyBwc2J0LnR4T3V0cHV0c1tvdXRwdXRJbmRleF1cbiAgICogdG8gdGhlbiBqdXN0IGdldCB0aGUgc2NyaXB0LiBIZXJlLCB3ZSBhcmUgZG9pbmcgdGhlIHNhbWUgdGhpbmcgYXMgd2hhdCB0eE91dHB1dHMoKSBkb2VzIGluXG4gICAqIGJpdGNvaW5qcy1saWIsIGJ1dCB3aXRob3V0IGl0ZXJhdGluZyBvdmVyIGVhY2ggb3V0cHV0LlxuICAgKiBAcGFyYW0gb3V0cHV0SW5kZXhcbiAgICogQHJldHVybnMgb3V0cHV0IHNjcmlwdCBhdCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICovXG4gIGdldE91dHB1dFNjcmlwdChvdXRwdXRJbmRleDogbnVtYmVyKTogQnVmZmVyIHtcbiAgICByZXR1cm4gKHRoaXMgYXMgYW55KS5fX0NBQ0hFLl9fVFgub3V0c1tvdXRwdXRJbmRleF0uc2NyaXB0IGFzIEJ1ZmZlcjtcbiAgfVxuXG4gIGdldE5vbldpdG5lc3NQcmV2aW91c1R4aWRzKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB0eElucHV0cyA9IHRoaXMudHhJbnB1dHM7IC8vIFRoZXNlIGFyZSBzb21ld2hhdCBjb3N0bHkgdG8gZXh0cmFjdFxuICAgIGNvbnN0IHR4aWRTZXQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICB0aGlzLmRhdGEuaW5wdXRzLmZvckVhY2goKGlucHV0LCBpbmRleCkgPT4ge1xuICAgICAgaWYgKCFpbnB1dC53aXRuZXNzVXR4bykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ011c3QgaGF2ZSB3aXRuZXNzIFVUWE8gZm9yIGFsbCBpbnB1dHMnKTtcbiAgICAgIH1cbiAgICAgIGlmICghaXNTZWd3aXQoaW5wdXQud2l0bmVzc1V0eG8uc2NyaXB0LCBpbnB1dC5yZWRlZW1TY3JpcHQpKSB7XG4gICAgICAgIHR4aWRTZXQuYWRkKGdldE91dHB1dElkRm9ySW5wdXQodHhJbnB1dHNbaW5kZXhdKS50eGlkKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gWy4uLnR4aWRTZXRdO1xuICB9XG5cbiAgYWRkTm9uV2l0bmVzc1V0eG9zKHR4QnVmczogUmVjb3JkPHN0cmluZywgQnVmZmVyPik6IHRoaXMge1xuICAgIGNvbnN0IHR4SW5wdXRzID0gdGhpcy50eElucHV0czsgLy8gVGhlc2UgYXJlIHNvbWV3aGF0IGNvc3RseSB0byBleHRyYWN0XG4gICAgdGhpcy5kYXRhLmlucHV0cy5mb3JFYWNoKChpbnB1dCwgaW5kZXgpID0+IHtcbiAgICAgIGlmICghaW5wdXQud2l0bmVzc1V0eG8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNdXN0IGhhdmUgd2l0bmVzcyBVVFhPIGZvciBhbGwgaW5wdXRzJyk7XG4gICAgICB9XG4gICAgICBpZiAoIWlzU2Vnd2l0KGlucHV0LndpdG5lc3NVdHhvLnNjcmlwdCwgaW5wdXQucmVkZWVtU2NyaXB0KSkge1xuICAgICAgICBjb25zdCB7IHR4aWQgfSA9IGdldE91dHB1dElkRm9ySW5wdXQodHhJbnB1dHNbaW5kZXhdKTtcbiAgICAgICAgaWYgKHR4QnVmc1t0eGlkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgYWxsIHJlcXVpcmVkIHByZXZpb3VzIHRyYW5zYWN0aW9ucyBwcm92aWRlZCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlSW5wdXQoaW5kZXgsIHsgbm9uV2l0bmVzc1V0eG86IHR4QnVmc1t0eGlkXSB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHN0YXRpYyBmcm9tVHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+LCBwcmV2T3V0cHV0czogVHhPdXRwdXQ8YmlnaW50PltdKTogVXR4b1BzYnQge1xuICAgIGlmIChwcmV2T3V0cHV0cy5sZW5ndGggIT09IHRyYW5zYWN0aW9uLmlucy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRyYW5zYWN0aW9uIGhhcyAke3RyYW5zYWN0aW9uLmlucy5sZW5ndGh9IGlucHV0cywgYnV0ICR7cHJldk91dHB1dHMubGVuZ3RofSBwcmV2aW91cyBvdXRwdXRzIHByb3ZpZGVkYFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgY2xvbmVkVHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbi5jbG9uZSgpO1xuICAgIGNvbnN0IHVwZGF0ZXMgPSB1bnNpZ24oY2xvbmVkVHJhbnNhY3Rpb24sIHByZXZPdXRwdXRzKTtcblxuICAgIGNvbnN0IHBzYnRCYXNlID0gbmV3IFBzYnRCYXNlKG5ldyBQc2J0VHJhbnNhY3Rpb24oeyB0eDogY2xvbmVkVHJhbnNhY3Rpb24gfSkpO1xuICAgIGNsb25lZFRyYW5zYWN0aW9uLmlucy5mb3JFYWNoKCgpID0+IHBzYnRCYXNlLmlucHV0cy5wdXNoKHsgdW5rbm93bktleVZhbHM6IFtdIH0pKTtcbiAgICBjbG9uZWRUcmFuc2FjdGlvbi5vdXRzLmZvckVhY2goKCkgPT4gcHNidEJhc2Uub3V0cHV0cy5wdXNoKHsgdW5rbm93bktleVZhbHM6IFtdIH0pKTtcbiAgICBjb25zdCBwc2J0ID0gdGhpcy5jcmVhdGVQc2J0KHsgbmV0d29yazogdHJhbnNhY3Rpb24ubmV0d29yayB9LCBwc2J0QmFzZSk7XG5cbiAgICB1cGRhdGVzLmZvckVhY2goKHVwZGF0ZSwgaW5kZXgpID0+IHtcbiAgICAgIHBzYnQudXBkYXRlSW5wdXQoaW5kZXgsIHVwZGF0ZSk7XG4gICAgICBwc2J0LnVwZGF0ZUlucHV0KGluZGV4LCB7IHdpdG5lc3NVdHhvOiB7IHNjcmlwdDogcHJldk91dHB1dHNbaW5kZXhdLnNjcmlwdCwgdmFsdWU6IHByZXZPdXRwdXRzW2luZGV4XS52YWx1ZSB9IH0pO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHBzYnQ7XG4gIH1cblxuICBnZXRVbnNpZ25lZFR4KCk6IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+IHtcbiAgICByZXR1cm4gdGhpcy50eC5jbG9uZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyBuZXdUcmFuc2FjdGlvbihuZXR3b3JrOiBOZXR3b3JrKTogVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4ge1xuICAgIHJldHVybiBuZXcgVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4obmV0d29yayk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHR4KCk6IFR4IHtcbiAgICByZXR1cm4gKHRoaXMuZGF0YS5nbG9iYWxNYXAudW5zaWduZWRUeCBhcyBQc2J0VHJhbnNhY3Rpb24pLnR4IGFzIFR4O1xuICB9XG5cbiAgcHJvdGVjdGVkIGNoZWNrRm9yU2lnbmF0dXJlcyhwcm9wTmFtZT86IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQpID0+IHtcbiAgICAgIGlmIChpbnB1dC50YXBTY3JpcHRTaWc/Lmxlbmd0aCB8fCBpbnB1dC50YXBLZXlTaWcgfHwgaW5wdXQucGFydGlhbFNpZz8ubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IG1vZGlmeSAke3Byb3BOYW1lID8/ICd0cmFuc2FjdGlvbid9IC0gc2lnbmF0dXJlcyBleGlzdC5gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBpbnB1dCBhdCBpbnB1dEluZGV4IGlzIGEgdGFwcm9vdCBrZXkgcGF0aC5cbiAgICogQ2hlY2tzIGZvciBwcmVzZW5jZSBvZiBtaW5pbXVtIHJlcXVpcmVkIGtleSBwYXRoIGlucHV0IGZpZWxkcyBhbmQgYWJzZW5jZSBvZiBhbnkgc2NyaXB0IHBhdGggb25seSBpbnB1dCBmaWVsZHMuXG4gICAqL1xuICBpc1RhcHJvb3RLZXlQYXRoSW5wdXQoaW5wdXRJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaW5wdXQgPSBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIHJldHVybiAoXG4gICAgICAhIWlucHV0LnRhcEludGVybmFsS2V5ICYmXG4gICAgICAhIWlucHV0LnRhcE1lcmtsZVJvb3QgJiZcbiAgICAgICEoXG4gICAgICAgIGlucHV0LnRhcExlYWZTY3JpcHQ/Lmxlbmd0aCB8fFxuICAgICAgICBpbnB1dC50YXBTY3JpcHRTaWc/Lmxlbmd0aCB8fFxuICAgICAgICBpbnB1dC50YXBCaXAzMkRlcml2YXRpb24/LnNvbWUoKHYpID0+IHYubGVhZkhhc2hlcy5sZW5ndGgpXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBpbnB1dCBhdCBpbnB1dEluZGV4IGlzIGEgdGFwcm9vdCBzY3JpcHQgcGF0aC5cbiAgICogQ2hlY2tzIGZvciBwcmVzZW5jZSBvZiBtaW5pbXVtIHJlcXVpcmVkIHNjcmlwdCBwYXRoIGlucHV0IGZpZWxkcyBhbmQgYWJzZW5jZSBvZiBhbnkga2V5IHBhdGggb25seSBpbnB1dCBmaWVsZHMuXG4gICAqL1xuICBpc1RhcHJvb3RTY3JpcHRQYXRoSW5wdXQoaW5wdXRJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaW5wdXQgPSBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIHJldHVybiAoXG4gICAgICAhIWlucHV0LnRhcExlYWZTY3JpcHQ/Lmxlbmd0aCAmJlxuICAgICAgIShcbiAgICAgICAgdGhpcy5nZXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXRJbmRleCwge1xuICAgICAgICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICAgICAgICBzdWJ0eXBlOiBQcm9wcmlldGFyeUtleVN1YnR5cGUuTVVTSUcyX1BBUlRJQ0lQQU5UX1BVQl9LRVlTLFxuICAgICAgICB9KS5sZW5ndGggfHxcbiAgICAgICAgdGhpcy5nZXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXRJbmRleCwge1xuICAgICAgICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICAgICAgICBzdWJ0eXBlOiBQcm9wcmlldGFyeUtleVN1YnR5cGUuTVVTSUcyX1BVQl9OT05DRSxcbiAgICAgICAgfSkubGVuZ3RoIHx8XG4gICAgICAgIHRoaXMuZ2V0UHJvcHJpZXRhcnlLZXlWYWxzKGlucHV0SW5kZXgsIHtcbiAgICAgICAgICBpZGVudGlmaWVyOiBQU0JUX1BST1BSSUVUQVJZX0lERU5USUZJRVIsXG4gICAgICAgICAgc3VidHlwZTogUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QQVJUSUFMX1NJRyxcbiAgICAgICAgfSkubGVuZ3RoXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBpbnB1dCBhdCBpbnB1dEluZGV4IGlzIGEgdGFwcm9vdFxuICAgKi9cbiAgaXNUYXByb290SW5wdXQoaW5wdXRJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaW5wdXQgPSBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIGNvbnN0IGlzUDJUUiA9IChzY3JpcHQ6IEJ1ZmZlcik6IGJvb2xlYW4gPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZ2V0VGFwcm9vdE91dHB1dEtleShzY3JpcHQpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuICEhKFxuICAgICAgaW5wdXQudGFwSW50ZXJuYWxLZXkgfHxcbiAgICAgIGlucHV0LnRhcE1lcmtsZVJvb3QgfHxcbiAgICAgIGlucHV0LnRhcExlYWZTY3JpcHQ/Lmxlbmd0aCB8fFxuICAgICAgaW5wdXQudGFwQmlwMzJEZXJpdmF0aW9uPy5sZW5ndGggfHxcbiAgICAgIGlucHV0LnRhcFNjcmlwdFNpZz8ubGVuZ3RoIHx8XG4gICAgICB0aGlzLmdldFByb3ByaWV0YXJ5S2V5VmFscyhpbnB1dEluZGV4LCB7XG4gICAgICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICAgICAgc3VidHlwZTogUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QQVJUSUNJUEFOVF9QVUJfS0VZUyxcbiAgICAgIH0pLmxlbmd0aCB8fFxuICAgICAgdGhpcy5nZXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXRJbmRleCwge1xuICAgICAgICBpZGVudGlmaWVyOiBQU0JUX1BST1BSSUVUQVJZX0lERU5USUZJRVIsXG4gICAgICAgIHN1YnR5cGU6IFByb3ByaWV0YXJ5S2V5U3VidHlwZS5NVVNJRzJfUFVCX05PTkNFLFxuICAgICAgfSkubGVuZ3RoIHx8XG4gICAgICB0aGlzLmdldFByb3ByaWV0YXJ5S2V5VmFscyhpbnB1dEluZGV4LCB7XG4gICAgICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICAgICAgc3VidHlwZTogUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QQVJUSUFMX1NJRyxcbiAgICAgIH0pLmxlbmd0aCB8fFxuICAgICAgKGlucHV0LndpdG5lc3NVdHhvICYmIGlzUDJUUihpbnB1dC53aXRuZXNzVXR4by5zY3JpcHQpKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGlzTXVsdGlzaWdUYXByb290U2NyaXB0KHNjcmlwdDogQnVmZmVyKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHBhcnNlUHViU2NyaXB0Mk9mMyhzY3JpcHQsICd0YXByb290U2NyaXB0UGF0aFNwZW5kJyk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vc3RseSBjb3BpZWQgZnJvbSBiaXRjb2luanMtbGliL3RzX3NyYy9wc2J0LnRzXG4gICAqL1xuICBmaW5hbGl6ZUFsbElucHV0cygpOiB0aGlzIHtcbiAgICBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIDApOyAvLyBtYWtpbmcgc3VyZSB3ZSBoYXZlIGF0IGxlYXN0IG9uZVxuICAgIHRoaXMuZGF0YS5pbnB1dHMubWFwKChpbnB1dCwgaWR4KSA9PiB7XG4gICAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdD8ubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzTXVsdGlzaWdUYXByb290U2NyaXB0KGlucHV0LnRhcExlYWZTY3JpcHRbMF0uc2NyaXB0KVxuICAgICAgICAgID8gdGhpcy5maW5hbGl6ZVRhcHJvb3RJbnB1dChpZHgpXG4gICAgICAgICAgOiB0aGlzLmZpbmFsaXplVGFwSW5wdXRXaXRoU2luZ2xlTGVhZlNjcmlwdEFuZFNpZ25hdHVyZShpZHgpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmlzVGFwcm9vdEtleVBhdGhJbnB1dChpZHgpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpbmFsaXplVGFwcm9vdE11c2lnMklucHV0KGlkeCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5maW5hbGl6ZUlucHV0KGlkeCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBmaW5hbGl6ZVRhcHJvb3RJbnB1dChpbnB1dEluZGV4OiBudW1iZXIpOiB0aGlzIHtcbiAgICBjb25zdCBzYW5pdGl6ZVNpZ25hdHVyZSA9IChzaWc6IEJ1ZmZlcikgPT4ge1xuICAgICAgY29uc3Qgc2lnaGFzaFR5cGUgPSBzaWcubGVuZ3RoID09PSA2NCA/IFRyYW5zYWN0aW9uLlNJR0hBU0hfREVGQVVMVCA6IHNpZy5yZWFkVUludDgoc2lnLmxlbmd0aCAtIDEpO1xuICAgICAgY29uc3QgaW5wdXRTaWdoYXNoVHlwZSA9IGlucHV0LnNpZ2hhc2hUeXBlID09PSB1bmRlZmluZWQgPyBUcmFuc2FjdGlvbi5TSUdIQVNIX0RFRkFVTFQgOiBpbnB1dC5zaWdoYXNoVHlwZTtcbiAgICAgIGFzc2VydChzaWdoYXNoVHlwZSA9PT0gaW5wdXRTaWdoYXNoVHlwZSwgJ3NpZ25hdHVyZSBzaWdoYXNoIGRvZXMgbm90IG1hdGNoIGlucHV0IHNpZ2hhc2ggdHlwZScpO1xuICAgICAgLy8gVE9ETyBCVEMtNjYzIFRoaXMgc2hvdWxkIGJlIGZpeGVkIGluIHBsYXRmb3JtLiBUaGlzIGlzIGp1c3QgYSB3b3JrYXJvdW5kIGZpeC5cbiAgICAgIHJldHVybiBzaWdoYXNoVHlwZSA9PT0gVHJhbnNhY3Rpb24uU0lHSEFTSF9ERUZBVUxUICYmIHNpZy5sZW5ndGggPT09IDY1ID8gc2lnLnNsaWNlKDAsIDY0KSA6IHNpZztcbiAgICB9O1xuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICAvLyB3aXRuZXNzID0gY29udHJvbC1ibG9jayBzY3JpcHQgZmlyc3Qtc2lnIHNlY29uZC1zaWdcbiAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdD8ubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIGxlYWYgc2NyaXB0IHN1cHBvcnRlZCBmb3IgZmluYWxpemluZycpO1xuICAgIH1cbiAgICBjb25zdCB7IGNvbnRyb2xCbG9jaywgc2NyaXB0IH0gPSBpbnB1dC50YXBMZWFmU2NyaXB0WzBdO1xuICAgIGNvbnN0IHdpdG5lc3M6IEJ1ZmZlcltdID0gW3NjcmlwdCwgY29udHJvbEJsb2NrXTtcbiAgICBjb25zdCBbcHVia2V5MSwgcHVia2V5Ml0gPSBwYXJzZVB1YlNjcmlwdDJPZjMoc2NyaXB0LCAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCcpLnB1YmxpY0tleXM7XG4gICAgZm9yIChjb25zdCBwayBvZiBbcHVia2V5MSwgcHVia2V5Ml0pIHtcbiAgICAgIGNvbnN0IHNpZyA9IGlucHV0LnRhcFNjcmlwdFNpZz8uZmluZCgoeyBwdWJrZXkgfSkgPT4gZXF1YWxQdWJsaWNLZXlJZ25vcmVZKHBrLCBwdWJrZXkpKTtcbiAgICAgIGlmICghc2lnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgc2lnbmF0dXJlcyBpbiBTY3JpcHQgU2lnLicpO1xuICAgICAgfVxuICAgICAgd2l0bmVzcy51bnNoaWZ0KHNhbml0aXplU2lnbmF0dXJlKHNpZy5zaWduYXR1cmUpKTtcbiAgICB9XG5cbiAgICBjb25zdCB3aXRuZXNzTGVuZ3RoID0gd2l0bmVzcy5yZWR1Y2UoKHMsIGIpID0+IHMgKyBiLmxlbmd0aCArIHZhcnVpbnQuZW5jb2RpbmdMZW5ndGgoYi5sZW5ndGgpLCAxKTtcblxuICAgIGNvbnN0IGJ1ZmZlcldyaXRlciA9IEJ1ZmZlcldyaXRlci53aXRoQ2FwYWNpdHkod2l0bmVzc0xlbmd0aCk7XG4gICAgYnVmZmVyV3JpdGVyLndyaXRlVmVjdG9yKHdpdG5lc3MpO1xuICAgIGNvbnN0IGZpbmFsU2NyaXB0V2l0bmVzcyA9IGJ1ZmZlcldyaXRlci5lbmQoKTtcblxuICAgIHRoaXMuZGF0YS51cGRhdGVJbnB1dChpbnB1dEluZGV4LCB7IGZpbmFsU2NyaXB0V2l0bmVzcyB9KTtcbiAgICB0aGlzLmRhdGEuY2xlYXJGaW5hbGl6ZWRJbnB1dChpbnB1dEluZGV4KTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmFsaXplcyBhIHRhcHJvb3QgbXVzaWcyIGlucHV0IGJ5IGFnZ3JlZ2F0aW5nIGFsbCBwYXJ0aWFsIHNpZ3MuXG4gICAqIElNUE9SVEFOVDogQWx3YXlzIGNhbGwgdmFsaWRhdGUqIGZ1bmN0aW9uIGJlZm9yZSBmaW5hbGl6aW5nLlxuICAgKi9cbiAgZmluYWxpemVUYXByb290TXVzaWcySW5wdXQoaW5wdXRJbmRleDogbnVtYmVyKTogdGhpcyB7XG4gICAgY29uc3QgaW5wdXQgPSBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIGNvbnN0IHBhcnRpYWxTaWdzID0gcGFyc2VQc2J0TXVzaWcyUGFydGlhbFNpZ3MoaW5wdXQpO1xuICAgIGlmIChwYXJ0aWFsU2lncz8ubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgbnVtYmVyIG9mIHBhcnRpYWwgc2lnbmF0dXJlcyAke3BhcnRpYWxTaWdzID8gcGFydGlhbFNpZ3MubGVuZ3RoIDogMH0gdG8gZmluYWxpemVgKTtcbiAgICB9XG4gICAgY29uc3QgeyBwYXJ0aWFsU2lnczogcFNpZ3MsIHNpZ0hhc2hUeXBlIH0gPSBnZXRTaWdIYXNoVHlwZUZyb21TaWdzKHBhcnRpYWxTaWdzKTtcbiAgICBjb25zdCB7IHNlc3Npb25LZXkgfSA9IHRoaXMuZ2V0TXVzaWcyU2Vzc2lvbktleShpbnB1dEluZGV4LCBzaWdIYXNoVHlwZSk7XG5cbiAgICBjb25zdCBhZ2dTaWcgPSBtdXNpZzJBZ2dyZWdhdGVTaWdzKFxuICAgICAgcFNpZ3MubWFwKChwU2lnKSA9PiBwU2lnLnBhcnRpYWxTaWcpLFxuICAgICAgc2Vzc2lvbktleVxuICAgICk7XG5cbiAgICBjb25zdCBzaWcgPSBzaWdIYXNoVHlwZSA9PT0gVHJhbnNhY3Rpb24uU0lHSEFTSF9ERUZBVUxUID8gYWdnU2lnIDogQnVmZmVyLmNvbmNhdChbYWdnU2lnLCBCdWZmZXIub2Yoc2lnSGFzaFR5cGUpXSk7XG5cbiAgICAvLyBzaW5nbGUgc2lnbmF0dXJlIHdpdGggNjQvNjUgYnl0ZXMgc2l6ZSBpcyBzY3JpcHQgd2l0bmVzcyBmb3Iga2V5IHBhdGggc3BlbmRcbiAgICBjb25zdCBidWZmZXJXcml0ZXIgPSBCdWZmZXJXcml0ZXIud2l0aENhcGFjaXR5KDEgKyB2YXJ1aW50LmVuY29kaW5nTGVuZ3RoKHNpZy5sZW5ndGgpICsgc2lnLmxlbmd0aCk7XG4gICAgYnVmZmVyV3JpdGVyLndyaXRlVmVjdG9yKFtzaWddKTtcbiAgICBjb25zdCBmaW5hbFNjcmlwdFdpdG5lc3MgPSBidWZmZXJXcml0ZXIuZW5kKCk7XG5cbiAgICB0aGlzLmRhdGEudXBkYXRlSW5wdXQoaW5wdXRJbmRleCwgeyBmaW5hbFNjcmlwdFdpdG5lc3MgfSk7XG4gICAgdGhpcy5kYXRhLmNsZWFyRmluYWxpemVkSW5wdXQoaW5wdXRJbmRleCk7XG4gICAgLy8gZGVsZXRpbmcgb25seSBCaXRHbyBwcm9wcmlldGFyeSBrZXkgdmFsdWVzLlxuICAgIHRoaXMuZGVsZXRlUHJvcHJpZXRhcnlLZXlWYWxzKGlucHV0SW5kZXgsIHsgaWRlbnRpZmllcjogUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgZmluYWxpemVUYXBJbnB1dFdpdGhTaW5nbGVMZWFmU2NyaXB0QW5kU2lnbmF0dXJlKGlucHV0SW5kZXg6IG51bWJlcik6IHRoaXMge1xuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdD8ubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIGxlYWYgc2NyaXB0IHN1cHBvcnRlZCBmb3IgZmluYWxpemluZycpO1xuICAgIH1cbiAgICBpZiAoaW5wdXQudGFwU2NyaXB0U2lnPy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgc2lnbmF0dXJlcyBpbiBTY3JpcHQgU2lnLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgY29udHJvbEJsb2NrLCBzY3JpcHQgfSA9IGlucHV0LnRhcExlYWZTY3JpcHRbMF07XG4gICAgY29uc3Qgd2l0bmVzczogQnVmZmVyW10gPSBbaW5wdXQudGFwU2NyaXB0U2lnWzBdLnNpZ25hdHVyZSwgc2NyaXB0LCBjb250cm9sQmxvY2tdO1xuICAgIGNvbnN0IHdpdG5lc3NMZW5ndGggPSB3aXRuZXNzLnJlZHVjZSgocywgYikgPT4gcyArIGIubGVuZ3RoICsgdmFydWludC5lbmNvZGluZ0xlbmd0aChiLmxlbmd0aCksIDEpO1xuXG4gICAgY29uc3QgYnVmZmVyV3JpdGVyID0gQnVmZmVyV3JpdGVyLndpdGhDYXBhY2l0eSh3aXRuZXNzTGVuZ3RoKTtcbiAgICBidWZmZXJXcml0ZXIud3JpdGVWZWN0b3Iod2l0bmVzcyk7XG4gICAgY29uc3QgZmluYWxTY3JpcHRXaXRuZXNzID0gYnVmZmVyV3JpdGVyLmVuZCgpO1xuXG4gICAgdGhpcy5kYXRhLnVwZGF0ZUlucHV0KGlucHV0SW5kZXgsIHsgZmluYWxTY3JpcHRXaXRuZXNzIH0pO1xuICAgIHRoaXMuZGF0YS5jbGVhckZpbmFsaXplZElucHV0KGlucHV0SW5kZXgpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogTW9zdGx5IGNvcGllZCBmcm9tIGJpdGNvaW5qcy1saWIvdHNfc3JjL3BzYnQudHNcbiAgICpcbiAgICogVW5saWtlIHRoZSBmdW5jdGlvbiBpdCBvdmVycmlkZXMsIHRoaXMgZG9lcyBub3QgdGFrZSBhIHZhbGlkYXRvci4gSW4gQml0R29cbiAgICogY29udGV4dCwgd2Uga25vdyBob3cgd2Ugd2FudCB0byB2YWxpZGF0ZSBzbyB3ZSBqdXN0IGhhcmQgY29kZSB0aGUgcmlnaHRcbiAgICogdmFsaWRhdG9yLlxuICAgKi9cbiAgdmFsaWRhdGVTaWduYXR1cmVzT2ZBbGxJbnB1dHMoKTogYm9vbGVhbiB7XG4gICAgY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCAwKTsgLy8gbWFraW5nIHN1cmUgd2UgaGF2ZSBhdCBsZWFzdCBvbmVcbiAgICBjb25zdCByZXN1bHRzID0gdGhpcy5kYXRhLmlucHV0cy5tYXAoKGlucHV0LCBpZHgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlU2lnbmF0dXJlc09mSW5wdXRDb21tb24oaWR4KTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0cy5yZWR1Y2UoKGZpbmFsLCByZXMpID0+IHJlcyAmJiBmaW5hbCwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgdHJ1ZSBpZmYgYW55IG1hdGNoaW5nIHZhbGlkIHNpZ25hdHVyZSBpcyBmb3VuZCBmb3IgYSBkZXJpdmVkIHB1YiBrZXkgZnJvbSBnaXZlbiBIRCBrZXkgcGFpci5cbiAgICovXG4gIHZhbGlkYXRlU2lnbmF0dXJlc09mSW5wdXRIRChpbnB1dEluZGV4OiBudW1iZXIsIGhkS2V5UGFpcjogQklQMzJJbnRlcmZhY2UpOiBib29sZWFuIHtcbiAgICBjb25zdCBpbnB1dCA9IGNoZWNrRm9ySW5wdXQodGhpcy5kYXRhLmlucHV0cywgaW5wdXRJbmRleCk7XG4gICAgY29uc3QgcHViS2V5ID0gVXR4b1BzYnQuZGVyaXZlS2V5UGFpckZvcklucHV0KGhkS2V5UGFpciwgaW5wdXQpO1xuICAgIGlmICghcHViS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NhbiBub3QgZGVyaXZlIGZyb20gSEQga2V5IHBhaXInKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGVTaWduYXR1cmVzT2ZJbnB1dENvbW1vbihpbnB1dEluZGV4LCBwdWJLZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHRydWUgaWZmIGFueSB2YWxpZCBzaWduYXR1cmUocykgYXJlIGZvdW5kIGZyb20gYmlwMzIgZGF0YSBvZiBQU0JUIG9yIGZvciBnaXZlbiBwdWIga2V5LlxuICAgKi9cbiAgdmFsaWRhdGVTaWduYXR1cmVzT2ZJbnB1dENvbW1vbihpbnB1dEluZGV4OiBudW1iZXIsIHB1YmtleT86IEJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5pc1RhcHJvb3RTY3JpcHRQYXRoSW5wdXQoaW5wdXRJbmRleCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVUYXByb290U2lnbmF0dXJlc09mSW5wdXQoaW5wdXRJbmRleCwgcHVia2V5KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc1RhcHJvb3RLZXlQYXRoSW5wdXQoaW5wdXRJbmRleCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVUYXByb290TXVzaWcyU2lnbmF0dXJlc09mSW5wdXQoaW5wdXRJbmRleCwgcHVia2V5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlU2lnbmF0dXJlc09mSW5wdXQoaW5wdXRJbmRleCwgKHAsIG0sIHMpID0+IGVjY0xpYi52ZXJpZnkobSwgcCwgcywgdHJ1ZSksIHB1YmtleSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBOb3QgYW4gZWxlZ2FudCBzb2x1dGlvbi4gTWlnaHQgbmVlZCB1cHN0cmVhbSBjaGFuZ2VzIGxpa2UgY3VzdG9tIGVycm9yIHR5cGVzLlxuICAgICAgaWYgKGVyci5tZXNzYWdlID09PSAnTm8gc2lnbmF0dXJlcyBmb3IgdGhpcyBwdWJrZXknKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldE11c2lnMlNlc3Npb25LZXkoXG4gICAgaW5wdXRJbmRleDogbnVtYmVyLFxuICAgIHNpZ0hhc2hUeXBlOiBudW1iZXJcbiAgKToge1xuICAgIHBhcnRpY2lwYW50czogUHNidE11c2lnMlBhcnRpY2lwYW50cztcbiAgICBub25jZXM6IFR1cGxlPFBzYnRNdXNpZzJQdWJOb25jZT47XG4gICAgaGFzaDogQnVmZmVyO1xuICAgIHNlc3Npb25LZXk6IFNlc3Npb25LZXk7XG4gIH0ge1xuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICBpZiAoIWlucHV0LnRhcEludGVybmFsS2V5IHx8ICFpbnB1dC50YXBNZXJrbGVSb290KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JvdGggdGFwSW50ZXJuYWxLZXkgYW5kIHRhcE1lcmtsZVJvb3QgYXJlIHJlcXVpcmVkJyk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFydGljaXBhbnRzID0gdGhpcy5nZXRNdXNpZzJQYXJ0aWNpcGFudHMoaW5wdXRJbmRleCwgaW5wdXQudGFwSW50ZXJuYWxLZXksIGlucHV0LnRhcE1lcmtsZVJvb3QpO1xuICAgIGNvbnN0IG5vbmNlcyA9IHRoaXMuZ2V0TXVzaWcyTm9uY2VzKGlucHV0SW5kZXgsIHBhcnRpY2lwYW50cyk7XG5cbiAgICBjb25zdCB7IGhhc2ggfSA9IHRoaXMuZ2V0VGFwcm9vdEhhc2hGb3JTaWcoaW5wdXRJbmRleCwgW3NpZ0hhc2hUeXBlXSk7XG5cbiAgICBjb25zdCBzZXNzaW9uS2V5ID0gY3JlYXRlTXVzaWcyU2lnbmluZ1Nlc3Npb24oe1xuICAgICAgcHViTm9uY2VzOiBbbm9uY2VzWzBdLnB1Yk5vbmNlLCBub25jZXNbMV0ucHViTm9uY2VdLFxuICAgICAgcHViS2V5czogcGFydGljaXBhbnRzLnBhcnRpY2lwYW50UHViS2V5cyxcbiAgICAgIHR4SGFzaDogaGFzaCxcbiAgICAgIGludGVybmFsUHViS2V5OiBpbnB1dC50YXBJbnRlcm5hbEtleSxcbiAgICAgIHRhcFRyZWVSb290OiBpbnB1dC50YXBNZXJrbGVSb290LFxuICAgIH0pO1xuICAgIHJldHVybiB7IHBhcnRpY2lwYW50cywgbm9uY2VzLCBoYXNoLCBzZXNzaW9uS2V5IH07XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgdHJ1ZSBmb3IgZm9sbG93aW5nIGNhc2VzLlxuICAgKiBJZiB2YWxpZCBtdXNpZzIgcGFydGlhbCBzaWduYXR1cmVzIGV4aXN0cyBmb3IgYm90aCAyIGtleXMsIGl0IHdpbGwgYWxzbyB2ZXJpZnkgYWdncmVnYXRlZCBzaWdcbiAgICogZm9yIGFnZ3JlZ2F0ZWQgdHdlYWtlZCBrZXkgKG91dHB1dCBrZXkpLCBvdGhlcndpc2Ugb25seSB2ZXJpZmllcyBwYXJ0aWFsIHNpZy5cbiAgICogSWYgcHVia2V5IGlzIHBhc3NlZCBpbiBpbnB1dCwgaXQgd2lsbCBjaGVjayBzaWcgb25seSBmb3IgdGhhdCBwdWJrZXksXG4gICAqIGlmIG5vIHNpZyBleGl0cyBmb3Igc3VjaCBrZXksIHRocm93cyBlcnJvci5cbiAgICogRm9yIGludmFsaWQgc3RhdGUgb2YgaW5wdXQgZGF0YSwgaXQgd2lsbCB0aHJvdyBlcnJvcnMuXG4gICAqL1xuICB2YWxpZGF0ZVRhcHJvb3RNdXNpZzJTaWduYXR1cmVzT2ZJbnB1dChpbnB1dEluZGV4OiBudW1iZXIsIHB1YmtleT86IEJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICBjb25zdCBwYXJ0aWFsU2lncyA9IHBhcnNlUHNidE11c2lnMlBhcnRpYWxTaWdzKGlucHV0KTtcbiAgICBpZiAoIXBhcnRpYWxTaWdzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHNpZ25hdHVyZXMgdG8gdmFsaWRhdGVgKTtcbiAgICB9XG5cbiAgICBsZXQgbXlQYXJ0aWFsU2lncyA9IHBhcnRpYWxTaWdzO1xuICAgIGlmIChwdWJrZXkpIHtcbiAgICAgIG15UGFydGlhbFNpZ3MgPSBwYXJ0aWFsU2lncy5maWx0ZXIoKGt2KSA9PiBlcXVhbFB1YmxpY0tleUlnbm9yZVkoa3YucGFydGljaXBhbnRQdWJLZXksIHB1YmtleSkpO1xuICAgICAgaWYgKG15UGFydGlhbFNpZ3M/Lmxlbmd0aCA8IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBzaWduYXR1cmVzIGZvciB0aGlzIHB1YmtleScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHsgcGFydGlhbFNpZ3M6IG15U2lncywgc2lnSGFzaFR5cGUgfSA9IGdldFNpZ0hhc2hUeXBlRnJvbVNpZ3MobXlQYXJ0aWFsU2lncyk7XG4gICAgY29uc3QgeyBwYXJ0aWNpcGFudHMsIG5vbmNlcywgaGFzaCwgc2Vzc2lvbktleSB9ID0gdGhpcy5nZXRNdXNpZzJTZXNzaW9uS2V5KGlucHV0SW5kZXgsIHNpZ0hhc2hUeXBlKTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSBteVNpZ3MubWFwKChteVNpZykgPT4ge1xuICAgICAgY29uc3QgbXlOb25jZSA9IG5vbmNlcy5maW5kKChrdikgPT4gZXF1YWxQdWJsaWNLZXlJZ25vcmVZKGt2LnBhcnRpY2lwYW50UHViS2V5LCBteVNpZy5wYXJ0aWNpcGFudFB1YktleSkpO1xuICAgICAgaWYgKCFteU5vbmNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRm91bmQgbm8gcHViIG5vbmNlIGZvciBwdWJrZXknKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtdXNpZzJQYXJ0aWFsU2lnVmVyaWZ5KG15U2lnLnBhcnRpYWxTaWcsIG15U2lnLnBhcnRpY2lwYW50UHViS2V5LCBteU5vbmNlLnB1Yk5vbmNlLCBzZXNzaW9uS2V5KTtcbiAgICB9KTtcblxuICAgIC8vIEZvciB2YWxpZCBzaW5nbGUgc2lnIG9yIDEgb3IgMiBmYWlsdXJlIHNpZ3MsIG5vIG5lZWQgdG8gdmFsaWRhdGUgYWdncmVnYXRlZCBzaWcuIFNvIHNraXAuXG4gICAgY29uc3QgcmVzdWx0ID0gcmVzdWx0cy5ldmVyeSgocmVzKSA9PiByZXMpO1xuICAgIGlmICghcmVzdWx0IHx8IG15U2lncy5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IGFnZ1NpZyA9IG11c2lnMkFnZ3JlZ2F0ZVNpZ3MoXG4gICAgICBteVNpZ3MubWFwKChteVNpZykgPT4gbXlTaWcucGFydGlhbFNpZyksXG4gICAgICBzZXNzaW9uS2V5XG4gICAgKTtcblxuICAgIHJldHVybiBlY2NMaWIudmVyaWZ5U2Nobm9ycihoYXNoLCBwYXJ0aWNpcGFudHMudGFwT3V0cHV0S2V5LCBhZ2dTaWcpO1xuICB9XG5cbiAgdmFsaWRhdGVUYXByb290U2lnbmF0dXJlc09mSW5wdXQoaW5wdXRJbmRleDogbnVtYmVyLCBwdWJrZXk/OiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCBpbnB1dCA9IHRoaXMuZGF0YS5pbnB1dHNbaW5wdXRJbmRleF07XG4gICAgY29uc3QgdGFwU2lncyA9IChpbnB1dCB8fCB7fSkudGFwU2NyaXB0U2lnO1xuICAgIGlmICghaW5wdXQgfHwgIXRhcFNpZ3MgfHwgdGFwU2lncy5sZW5ndGggPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHNpZ25hdHVyZXMgdG8gdmFsaWRhdGUnKTtcbiAgICB9XG4gICAgbGV0IG15U2lncztcbiAgICBpZiAocHVia2V5KSB7XG4gICAgICBteVNpZ3MgPSB0YXBTaWdzLmZpbHRlcigoc2lnKSA9PiBlcXVhbFB1YmxpY0tleUlnbm9yZVkoc2lnLnB1YmtleSwgcHVia2V5KSk7XG4gICAgICBpZiAobXlTaWdzLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBzaWduYXR1cmVzIGZvciB0aGlzIHB1YmtleScpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBteVNpZ3MgPSB0YXBTaWdzO1xuICAgIH1cbiAgICBjb25zdCByZXN1bHRzOiBib29sZWFuW10gPSBbXTtcblxuICAgIGFzc2VydChpbnB1dC50YXBMZWFmU2NyaXB0Py5sZW5ndGggPT09IDEsIGBzaW5nbGUgdGFwTGVhZlNjcmlwdCBpcyBleHBlY3RlZC4gR290ICR7aW5wdXQudGFwTGVhZlNjcmlwdD8ubGVuZ3RofWApO1xuICAgIGNvbnN0IFt0YXBMZWFmU2NyaXB0XSA9IGlucHV0LnRhcExlYWZTY3JpcHQ7XG4gICAgY29uc3QgcHViS2V5cyA9IHRoaXMuaXNNdWx0aXNpZ1RhcHJvb3RTY3JpcHQodGFwTGVhZlNjcmlwdC5zY3JpcHQpXG4gICAgICA/IHBhcnNlUHViU2NyaXB0Mk9mMyh0YXBMZWFmU2NyaXB0LnNjcmlwdCwgJ3RhcHJvb3RTY3JpcHRQYXRoU3BlbmQnKS5wdWJsaWNLZXlzXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGZvciAoY29uc3QgcFNpZyBvZiBteVNpZ3MpIHtcbiAgICAgIGNvbnN0IHsgc2lnbmF0dXJlLCBsZWFmSGFzaCwgcHVia2V5IH0gPSBwU2lnO1xuICAgICAgaWYgKHB1YktleXMpIHtcbiAgICAgICAgYXNzZXJ0KFxuICAgICAgICAgIHB1YktleXMuZmluZCgocGspID0+IHB1YmtleS5lcXVhbHMocGspKSxcbiAgICAgICAgICAncHVibGljIGtleSBub3QgZm91bmQgaW4gdGFwIGxlYWYgc2NyaXB0J1xuICAgICAgICApO1xuICAgICAgfVxuICAgICAgbGV0IHNpZ0hhc2hUeXBlOiBudW1iZXI7XG4gICAgICBsZXQgc2lnOiBCdWZmZXI7XG4gICAgICBpZiAoc2lnbmF0dXJlLmxlbmd0aCA9PT0gNjUpIHtcbiAgICAgICAgc2lnSGFzaFR5cGUgPSBzaWduYXR1cmVbNjRdO1xuICAgICAgICBzaWcgPSBzaWduYXR1cmUuc2xpY2UoMCwgNjQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2lnSGFzaFR5cGUgPSBUcmFuc2FjdGlvbi5TSUdIQVNIX0RFRkFVTFQ7XG4gICAgICAgIHNpZyA9IHNpZ25hdHVyZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgaGFzaCB9ID0gdGhpcy5nZXRUYXByb290SGFzaEZvclNpZyhpbnB1dEluZGV4LCBbc2lnSGFzaFR5cGVdLCBsZWFmSGFzaCk7XG4gICAgICByZXN1bHRzLnB1c2goZWNjTGliLnZlcmlmeVNjaG5vcnIoaGFzaCwgcHVia2V5LCBzaWcpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHMuZXZlcnkoKHJlcykgPT4gcmVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gaW5wdXRJbmRleFxuICAgKiBAcGFyYW0gcm9vdE5vZGVzIG9wdGlvbmFsIGlucHV0IHJvb3QgYmlwMzIgbm9kZXMgdG8gdmVyaWZ5IHdpdGguIElmIGl0IGlzIG5vdCBwcm92aWRlZCwgZ2xvYmFsWHB1YiB3aWxsIGJlIHVzZWQuXG4gICAqIEByZXR1cm4gYXJyYXkgb2YgYm9vbGVhbiB2YWx1ZXMuIFRydWUgd2hlbiBjb3JyZXNwb25kaW5nIGluZGV4IGluIGBwdWJsaWNLZXlzYCBoYXMgc2lnbmVkIHRoZSB0cmFuc2FjdGlvbi5cbiAgICogSWYgbm8gc2lnbmF0dXJlIGluIHRoZSB0eCBvciBubyBwdWJsaWMga2V5IG1hdGNoaW5nIHNpZ25hdHVyZSwgdGhlIHZhbGlkYXRpb24gaXMgY29uc2lkZXJlZCBhcyBmYWxzZS5cbiAgICogSWYgcm9vdE5vZGVzIGFyZSBub3QgZXhwbGljaXRseSBwYXNzZWQgaW4sIHRoZSByZXR1cm4gYXJyYXkgd2lsbCBiZSB1bm9yZGVyZWQuXG4gICAqIFVzZSBnZXRTb3J0ZWRSb290Tm9kZXMoKSBpbnN0ZWFkIGlmIG9yZGVyaW5nIGlzIGltcG9ydGFudC5cbiAgICovXG4gIGdldFNpZ25hdHVyZVZhbGlkYXRpb25BcnJheShcbiAgICBpbnB1dEluZGV4OiBudW1iZXIsXG4gICAgeyByb290Tm9kZXMgfTogeyByb290Tm9kZXM6IFRyaXBsZTxCSVAzMkludGVyZmFjZT4gfCB1bmRlZmluZWQgfVxuICApOiBUcmlwbGU8Ym9vbGVhbj4ge1xuICAgIGlmICghcm9vdE5vZGVzICYmICghdGhpcy5kYXRhLmdsb2JhbE1hcC5nbG9iYWxYcHViPy5sZW5ndGggfHwgIWlzVHJpcGxlKHRoaXMuZGF0YS5nbG9iYWxNYXAuZ2xvYmFsWHB1YikpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBnZXQgc2lnbmF0dXJlIHZhbGlkYXRpb24gYXJyYXkgd2l0aG91dCAzIGdsb2JhbCB4cHVicycpO1xuICAgIH1cblxuICAgIGNvbnN0IGJpcDMycyA9IHJvb3ROb2Rlc1xuICAgICAgPyByb290Tm9kZXNcbiAgICAgIDogdGhpcy5kYXRhLmdsb2JhbE1hcC5nbG9iYWxYcHViPy5tYXAoKHhwdWIpID0+XG4gICAgICAgICAgQklQMzJGYWN0b3J5KGVjY0xpYikuZnJvbUJhc2U1OChiczU4Y2hlY2suZW5jb2RlKHhwdWIuZXh0ZW5kZWRQdWJrZXkpKVxuICAgICAgICApO1xuXG4gICAgaWYgKCFiaXAzMnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZWl0aGVyIGdsb2JhbE1hcCBvciByb290Tm9kZXMgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dCA9IGNoZWNrRm9ySW5wdXQodGhpcy5kYXRhLmlucHV0cywgaW5wdXRJbmRleCk7XG4gICAgaWYgKCFnZXRQc2J0SW5wdXRTaWduYXR1cmVDb3VudChpbnB1dCkpIHtcbiAgICAgIHJldHVybiBbZmFsc2UsIGZhbHNlLCBmYWxzZV07XG4gICAgfVxuXG4gICAgcmV0dXJuIGJpcDMycy5tYXAoKGJpcDMyKSA9PiB7XG4gICAgICBjb25zdCBwdWJLZXkgPSBVdHhvUHNidC5kZXJpdmVLZXlQYWlyRm9ySW5wdXQoYmlwMzIsIGlucHV0KTtcbiAgICAgIGlmICghcHViS2V5KSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlU2lnbmF0dXJlc09mSW5wdXRDb21tb24oaW5wdXRJbmRleCwgcHViS2V5KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBOb3QgYW4gZWxlZ2FudCBzb2x1dGlvbi4gTWlnaHQgbmVlZCB1cHN0cmVhbSBjaGFuZ2VzIGxpa2UgY3VzdG9tIGVycm9yIHR5cGVzLlxuICAgICAgICBpZiAoZXJyLm1lc3NhZ2UgPT09ICdObyBzaWduYXR1cmVzIGZvciB0aGlzIHB1YmtleScpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH0pIGFzIFRyaXBsZTxib29sZWFuPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3N0bHkgY29waWVkIGZyb20gYml0Y29pbmpzLWxpYi90c19zcmMvcHNidC50c1xuICAgKi9cbiAgc2lnbkFsbElucHV0c0hEKFxuICAgIGhkS2V5UGFpcjogSERUYXByb290U2lnbmVyIHwgSERUYXByb290TXVzaWcyU2lnbmVyLFxuICAgIHBhcmFtcz86IG51bWJlcltdIHwgUGFydGlhbDxTaWduYXR1cmVQYXJhbXM+XG4gICk6IHRoaXMge1xuICAgIGlmICghaGRLZXlQYWlyIHx8ICFoZEtleVBhaXIucHVibGljS2V5IHx8ICFoZEtleVBhaXIuZmluZ2VycHJpbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTmVlZCBIRFNpZ25lciB0byBzaWduIGlucHV0Jyk7XG4gICAgfVxuICAgIGNvbnN0IHsgc2lnaGFzaFR5cGVzLCBkZXRlcm1pbmlzdGljIH0gPSB0b1NpZ25hdHVyZVBhcmFtcyh0aGlzLm5ldHdvcmssIHBhcmFtcyk7XG5cbiAgICBjb25zdCByZXN1bHRzOiBib29sZWFuW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZGF0YS5pbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuc2lnbklucHV0SEQoaSwgaGRLZXlQYWlyLCB7IHNpZ2hhc2hUeXBlcywgZGV0ZXJtaW5pc3RpYyB9KTtcbiAgICAgICAgcmVzdWx0cy5wdXNoKHRydWUpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlc3VsdHMucHVzaChmYWxzZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyZXN1bHRzLmV2ZXJ5KCh2KSA9PiAhdikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gaW5wdXRzIHdlcmUgc2lnbmVkJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vc3RseSBjb3BpZWQgZnJvbSBiaXRjb2luanMtbGliL3RzX3NyYy9wc2J0LnRzOnNpZ25JbnB1dEhEXG4gICAqL1xuICBzaWduVGFwcm9vdElucHV0SEQoXG4gICAgaW5wdXRJbmRleDogbnVtYmVyLFxuICAgIGhkS2V5UGFpcjogSERUYXByb290U2lnbmVyIHwgSERUYXByb290TXVzaWcyU2lnbmVyLFxuICAgIHsgc2lnaGFzaFR5cGVzID0gW1RyYW5zYWN0aW9uLlNJR0hBU0hfREVGQVVMVCwgVHJhbnNhY3Rpb24uU0lHSEFTSF9BTExdLCBkZXRlcm1pbmlzdGljID0gZmFsc2UgfSA9IHt9XG4gICk6IHRoaXMge1xuICAgIGlmICghdGhpcy5pc1RhcHJvb3RJbnB1dChpbnB1dEluZGV4KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdub3QgYSB0YXByb290IGlucHV0Jyk7XG4gICAgfVxuICAgIGlmICghaGRLZXlQYWlyIHx8ICFoZEtleVBhaXIucHVibGljS2V5IHx8ICFoZEtleVBhaXIuZmluZ2VycHJpbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTmVlZCBIRFNpZ25lciB0byBzaWduIGlucHV0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICBpZiAoIWlucHV0LnRhcEJpcDMyRGVyaXZhdGlvbiB8fCBpbnB1dC50YXBCaXAzMkRlcml2YXRpb24ubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05lZWQgdGFwQmlwMzJEZXJpdmF0aW9uIHRvIHNpZ24gVGFwcm9vdCB3aXRoIEhEJyk7XG4gICAgfVxuICAgIGNvbnN0IG15RGVyaXZhdGlvbnMgPSBpbnB1dC50YXBCaXAzMkRlcml2YXRpb25cbiAgICAgIC5tYXAoKGJpcER2KSA9PiB7XG4gICAgICAgIGlmIChiaXBEdi5tYXN0ZXJGaW5nZXJwcmludC5lcXVhbHMoaGRLZXlQYWlyLmZpbmdlcnByaW50KSkge1xuICAgICAgICAgIHJldHVybiBiaXBEdjtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC5maWx0ZXIoKHYpID0+ICEhdikgYXMgVGFwQmlwMzJEZXJpdmF0aW9uW107XG4gICAgaWYgKG15RGVyaXZhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05lZWQgb25lIHRhcEJpcDMyRGVyaXZhdGlvbiBtYXN0ZXJGaW5nZXJwcmludCB0byBtYXRjaCB0aGUgSERTaWduZXIgZmluZ2VycHJpbnQnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXREZXJpdmVkTm9kZShiaXBEdjogVGFwQmlwMzJEZXJpdmF0aW9uKTogSERUYXByb290TXVzaWcyU2lnbmVyIHwgSERUYXByb290U2lnbmVyIHtcbiAgICAgIGNvbnN0IG5vZGUgPSBoZEtleVBhaXIuZGVyaXZlUGF0aChiaXBEdi5wYXRoKTtcbiAgICAgIGlmICghZXF1YWxQdWJsaWNLZXlJZ25vcmVZKGJpcER2LnB1YmtleSwgbm9kZS5wdWJsaWNLZXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncHVia2V5IGRpZCBub3QgbWF0Y2ggdGFwQmlwMzJEZXJpdmF0aW9uJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG5cbiAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdD8ubGVuZ3RoKSB7XG4gICAgICBjb25zdCBzaWduZXJzOiBUYXByb290U2lnbmVyW10gPSBteURlcml2YXRpb25zLm1hcCgoYmlwRHYpID0+IHtcbiAgICAgICAgY29uc3Qgc2lnbmVyID0gZ2V0RGVyaXZlZE5vZGUoYmlwRHYpO1xuICAgICAgICBpZiAoISgnc2lnblNjaG5vcnInIGluIHNpZ25lcikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NpZ25TY2hub3JyIGZ1bmN0aW9uIGlzIHJlcXVpcmVkIHRvIHNpZ24gcDJ0cicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHNpZ25lciwgbGVhZkhhc2hlczogYmlwRHYubGVhZkhhc2hlcyB9O1xuICAgICAgfSk7XG4gICAgICBzaWduZXJzLmZvckVhY2goKHsgc2lnbmVyLCBsZWFmSGFzaGVzIH0pID0+IHRoaXMuc2lnblRhcHJvb3RJbnB1dChpbnB1dEluZGV4LCBzaWduZXIsIGxlYWZIYXNoZXMsIHNpZ2hhc2hUeXBlcykpO1xuICAgIH0gZWxzZSBpZiAoaW5wdXQudGFwSW50ZXJuYWxLZXk/Lmxlbmd0aCkge1xuICAgICAgY29uc3Qgc2lnbmVyczogTXVzaWcyU2lnbmVyW10gPSBteURlcml2YXRpb25zLm1hcCgoYmlwRHYpID0+IHtcbiAgICAgICAgY29uc3Qgc2lnbmVyID0gZ2V0RGVyaXZlZE5vZGUoYmlwRHYpO1xuICAgICAgICBpZiAoISgncHJpdmF0ZUtleScgaW4gc2lnbmVyKSB8fCAhc2lnbmVyLnByaXZhdGVLZXkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByaXZhdGVLZXkgaXMgcmVxdWlyZWQgdG8gc2lnbiBwMnRyIG11c2lnMicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzaWduZXI7XG4gICAgICB9KTtcbiAgICAgIHNpZ25lcnMuZm9yRWFjaCgoc2lnbmVyKSA9PiB0aGlzLnNpZ25UYXByb290TXVzaWcySW5wdXQoaW5wdXRJbmRleCwgc2lnbmVyLCB7IHNpZ2hhc2hUeXBlcywgZGV0ZXJtaW5pc3RpYyB9KSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2lnbklucHV0KGlucHV0SW5kZXg6IG51bWJlciwga2V5UGFpcjogU2lnbmVyLCBzaWdoYXNoVHlwZXM/OiBudW1iZXJbXSk6IHRoaXMge1xuICAgIGNvbnN0IHsgc2lnaGFzaFR5cGVzOiBzaWdoYXNoRm9yTmV0d29yayB9ID0gdG9TaWduYXR1cmVQYXJhbXModGhpcy5uZXR3b3JrLCBzaWdoYXNoVHlwZXMpO1xuICAgIHJldHVybiBzdXBlci5zaWduSW5wdXQoaW5wdXRJbmRleCwga2V5UGFpciwgc2lnaGFzaEZvck5ldHdvcmspO1xuICB9XG5cbiAgc2lnbklucHV0SEQoXG4gICAgaW5wdXRJbmRleDogbnVtYmVyLFxuICAgIGhkS2V5UGFpcjogSERUYXByb290U2lnbmVyIHwgSERUYXByb290TXVzaWcyU2lnbmVyLFxuICAgIHBhcmFtcz86IG51bWJlcltdIHwgUGFydGlhbDxTaWduYXR1cmVQYXJhbXM+XG4gICk6IHRoaXMge1xuICAgIGNvbnN0IHsgc2lnaGFzaFR5cGVzLCBkZXRlcm1pbmlzdGljIH0gPSB0b1NpZ25hdHVyZVBhcmFtcyh0aGlzLm5ldHdvcmssIHBhcmFtcyk7XG4gICAgaWYgKHRoaXMuaXNUYXByb290SW5wdXQoaW5wdXRJbmRleCkpIHtcbiAgICAgIHJldHVybiB0aGlzLnNpZ25UYXByb290SW5wdXRIRChpbnB1dEluZGV4LCBoZEtleVBhaXIsIHsgc2lnaGFzaFR5cGVzLCBkZXRlcm1pbmlzdGljIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc3VwZXIuc2lnbklucHV0SEQoaW5wdXRJbmRleCwgaGRLZXlQYWlyLCBzaWdoYXNoVHlwZXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0TXVzaWcyUGFydGljaXBhbnRzKGlucHV0SW5kZXg6IG51bWJlciwgdGFwSW50ZXJuYWxLZXk6IEJ1ZmZlciwgdGFwTWVya2xlUm9vdDogQnVmZmVyKSB7XG4gICAgY29uc3QgcGFydGljaXBhbnRzS2V5VmFsRGF0YSA9IHBhcnNlUHNidE11c2lnMlBhcnRpY2lwYW50cyh0aGlzLmRhdGEuaW5wdXRzW2lucHV0SW5kZXhdKTtcbiAgICBpZiAoIXBhcnRpY2lwYW50c0tleVZhbERhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm91bmQgMCBtYXRjaGluZyBwYXJ0aWNpcGFudCBrZXkgdmFsdWUgaW5zdGVhZCBvZiAxYCk7XG4gICAgfVxuICAgIGFzc2VydFBzYnRNdXNpZzJQYXJ0aWNpcGFudHMocGFydGljaXBhbnRzS2V5VmFsRGF0YSwgdGFwSW50ZXJuYWxLZXksIHRhcE1lcmtsZVJvb3QpO1xuICAgIHJldHVybiBwYXJ0aWNpcGFudHNLZXlWYWxEYXRhO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRNdXNpZzJOb25jZXMoaW5wdXRJbmRleDogbnVtYmVyLCBwYXJ0aWNpcGFudHNLZXlWYWxEYXRhOiBQc2J0TXVzaWcyUGFydGljaXBhbnRzKSB7XG4gICAgY29uc3Qgbm9uY2VzS2V5VmFsc0RhdGEgPSBwYXJzZVBzYnRNdXNpZzJOb25jZXModGhpcy5kYXRhLmlucHV0c1tpbnB1dEluZGV4XSk7XG4gICAgaWYgKCFub25jZXNLZXlWYWxzRGF0YSB8fCAhaXNUdXBsZShub25jZXNLZXlWYWxzRGF0YSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZvdW5kICR7bm9uY2VzS2V5VmFsc0RhdGE/Lmxlbmd0aCA/IG5vbmNlc0tleVZhbHNEYXRhLmxlbmd0aCA6IDB9IG1hdGNoaW5nIG5vbmNlIGtleSB2YWx1ZSBpbnN0ZWFkIG9mIDJgXG4gICAgICApO1xuICAgIH1cbiAgICBhc3NlcnRQc2J0TXVzaWcyTm9uY2VzKG5vbmNlc0tleVZhbHNEYXRhLCBwYXJ0aWNpcGFudHNLZXlWYWxEYXRhKTtcbiAgICByZXR1cm4gbm9uY2VzS2V5VmFsc0RhdGE7XG4gIH1cblxuICAvKipcbiAgICogU2lnbnMgcDJ0ciBtdXNpZzIga2V5IHBhdGggaW5wdXQgd2l0aCAyIGFnZ3JlZ2F0ZWQga2V5cy5cbiAgICpcbiAgICogTm90ZTogT25seSBjYW4gc2lnbiBkZXRlcm1pbmlzdGljYWxseSBhcyB0aGUgY29zaWduZXJcbiAgICogQHBhcmFtIGlucHV0SW5kZXhcbiAgICogQHBhcmFtIHNpZ25lciAtIFhZIHB1YmxpYyBrZXkgYW5kIHByaXZhdGUga2V5IGFyZSByZXF1aXJlZFxuICAgKiBAcGFyYW0gc2lnaGFzaFR5cGVzXG4gICAqIEBwYXJhbSBkZXRlcm1pbmlzdGljIElmIHRydWUsIHNpZ24gdGhlIG11c2lnIGlucHV0IGRldGVybWluaXN0aWNhbGx5XG4gICAqL1xuICBzaWduVGFwcm9vdE11c2lnMklucHV0KFxuICAgIGlucHV0SW5kZXg6IG51bWJlcixcbiAgICBzaWduZXI6IE11c2lnMlNpZ25lcixcbiAgICB7IHNpZ2hhc2hUeXBlcyA9IFtUcmFuc2FjdGlvbi5TSUdIQVNIX0RFRkFVTFQsIFRyYW5zYWN0aW9uLlNJR0hBU0hfQUxMXSwgZGV0ZXJtaW5pc3RpYyA9IGZhbHNlIH0gPSB7fVxuICApOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuaXNUYXByb290S2V5UGF0aElucHV0KGlucHV0SW5kZXgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vdCBhIHRhcHJvb3QgbXVzaWcyIGlucHV0Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgaW5wdXQgPSB0aGlzLmRhdGEuaW5wdXRzW2lucHV0SW5kZXhdO1xuXG4gICAgaWYgKCFpbnB1dC50YXBJbnRlcm5hbEtleSB8fCAhaW5wdXQudGFwTWVya2xlUm9vdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGlucHV0IGRhdGEnKTtcbiAgICB9XG5cbiAgICAvLyBSZXRyaWV2ZSBhbmQgY2hlY2sgdGhhdCB3ZSBoYXZlIHR3byBwYXJ0aWNpcGFudCBub25jZXNcbiAgICBjb25zdCBwYXJ0aWNpcGFudHMgPSB0aGlzLmdldE11c2lnMlBhcnRpY2lwYW50cyhpbnB1dEluZGV4LCBpbnB1dC50YXBJbnRlcm5hbEtleSwgaW5wdXQudGFwTWVya2xlUm9vdCk7XG4gICAgY29uc3QgeyB0YXBPdXRwdXRLZXksIHBhcnRpY2lwYW50UHViS2V5cyB9ID0gcGFydGljaXBhbnRzO1xuICAgIGNvbnN0IHNpZ25lclB1YktleSA9IHBhcnRpY2lwYW50UHViS2V5cy5maW5kKChwdWJLZXkpID0+IGVxdWFsUHVibGljS2V5SWdub3JlWShwdWJLZXksIHNpZ25lci5wdWJsaWNLZXkpKTtcbiAgICBpZiAoIXNpZ25lclB1YktleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzaWduZXIgcHViIGtleSBzaG91bGQgbWF0Y2ggb25lIG9mIHBhcnRpY2lwYW50IHB1YiBrZXlzJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9uY2VzID0gdGhpcy5nZXRNdXNpZzJOb25jZXMoaW5wdXRJbmRleCwgcGFydGljaXBhbnRzKTtcbiAgICBjb25zdCB7IGhhc2gsIHNpZ2hhc2hUeXBlIH0gPSB0aGlzLmdldFRhcHJvb3RIYXNoRm9yU2lnKGlucHV0SW5kZXgsIHNpZ2hhc2hUeXBlcyk7XG5cbiAgICBsZXQgcGFydGlhbFNpZzogQnVmZmVyO1xuICAgIGlmIChkZXRlcm1pbmlzdGljKSB7XG4gICAgICBpZiAoIWVxdWFsUHVibGljS2V5SWdub3JlWShzaWduZXJQdWJLZXksIHBhcnRpY2lwYW50UHViS2V5c1sxXSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW4gb25seSBhZGQgYSBkZXRlcm1pbmlzdGljIHNpZ25hdHVyZSBvbiB0aGUgY29zaWduZXInKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmlyc3RTaWduZXJOb25jZSA9IG5vbmNlcy5maW5kKChuKSA9PiBlcXVhbFB1YmxpY0tleUlnbm9yZVkobi5wYXJ0aWNpcGFudFB1YktleSwgcGFydGljaXBhbnRQdWJLZXlzWzBdKSk7XG4gICAgICBpZiAoIWZpcnN0U2lnbmVyTm9uY2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgZmluZCB0aGUgdXNlciBub25jZScpO1xuICAgICAgfVxuXG4gICAgICBwYXJ0aWFsU2lnID0gbXVzaWcyRGV0ZXJtaW5pc3RpY1NpZ24oe1xuICAgICAgICBwcml2YXRlS2V5OiBzaWduZXIucHJpdmF0ZUtleSxcbiAgICAgICAgb3RoZXJOb25jZTogZmlyc3RTaWduZXJOb25jZS5wdWJOb25jZSxcbiAgICAgICAgcHVibGljS2V5czogcGFydGljaXBhbnRQdWJLZXlzLFxuICAgICAgICBpbnRlcm5hbFB1YktleTogaW5wdXQudGFwSW50ZXJuYWxLZXksXG4gICAgICAgIHRhcFRyZWVSb290OiBpbnB1dC50YXBNZXJrbGVSb290LFxuICAgICAgICBoYXNoLFxuICAgICAgfSkuc2lnO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzZXNzaW9uS2V5ID0gY3JlYXRlTXVzaWcyU2lnbmluZ1Nlc3Npb24oe1xuICAgICAgICBwdWJOb25jZXM6IFtub25jZXNbMF0ucHViTm9uY2UsIG5vbmNlc1sxXS5wdWJOb25jZV0sXG4gICAgICAgIHB1YktleXM6IHBhcnRpY2lwYW50UHViS2V5cyxcbiAgICAgICAgdHhIYXNoOiBoYXNoLFxuICAgICAgICBpbnRlcm5hbFB1YktleTogaW5wdXQudGFwSW50ZXJuYWxLZXksXG4gICAgICAgIHRhcFRyZWVSb290OiBpbnB1dC50YXBNZXJrbGVSb290LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNpZ25lck5vbmNlID0gbm9uY2VzLmZpbmQoKGt2KSA9PiBlcXVhbFB1YmxpY0tleUlnbm9yZVkoa3YucGFydGljaXBhbnRQdWJLZXksIHNpZ25lclB1YktleSkpO1xuICAgICAgaWYgKCFzaWduZXJOb25jZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3B1Yk5vbmNlIGlzIG1pc3NpbmcuIHJldHJ5IHNpZ25pbmcgcHJvY2VzcycpO1xuICAgICAgfVxuICAgICAgcGFydGlhbFNpZyA9IG11c2lnMlBhcnRpYWxTaWduKHNpZ25lci5wcml2YXRlS2V5LCBzaWduZXJOb25jZS5wdWJOb25jZSwgc2Vzc2lvbktleSwgdGhpcy5ub25jZVN0b3JlKTtcbiAgICB9XG5cbiAgICBpZiAoc2lnaGFzaFR5cGUgIT09IFRyYW5zYWN0aW9uLlNJR0hBU0hfREVGQVVMVCkge1xuICAgICAgcGFydGlhbFNpZyA9IEJ1ZmZlci5jb25jYXQoW3BhcnRpYWxTaWcsIEJ1ZmZlci5vZihzaWdoYXNoVHlwZSldKTtcbiAgICB9XG5cbiAgICBjb25zdCBzaWcgPSBlbmNvZGVQc2J0TXVzaWcyUGFydGlhbFNpZyh7XG4gICAgICBwYXJ0aWNpcGFudFB1YktleTogc2lnbmVyUHViS2V5LFxuICAgICAgdGFwT3V0cHV0S2V5LFxuICAgICAgcGFydGlhbFNpZzogcGFydGlhbFNpZyxcbiAgICB9KTtcbiAgICB0aGlzLmFkZFByb3ByaWV0YXJ5S2V5VmFsVG9JbnB1dChpbnB1dEluZGV4LCBzaWcpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2lnblRhcHJvb3RJbnB1dChcbiAgICBpbnB1dEluZGV4OiBudW1iZXIsXG4gICAgc2lnbmVyOiBTY2hub3JyU2lnbmVyLFxuICAgIGxlYWZIYXNoZXM6IEJ1ZmZlcltdLFxuICAgIHNpZ2hhc2hUeXBlczogbnVtYmVyW10gPSBbVHJhbnNhY3Rpb24uU0lHSEFTSF9ERUZBVUxULCBUcmFuc2FjdGlvbi5TSUdIQVNIX0FMTF1cbiAgKTogdGhpcyB7XG4gICAgY29uc3QgaW5wdXQgPSBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIC8vIEZpZ3VyZSBvdXQgaWYgdGhpcyBpcyBzY3JpcHQgcGF0aCBvciBub3QsIGlmIG5vdCwgdHdlYWsgdGhlIHByaXZhdGUga2V5XG4gICAgaWYgKCFpbnB1dC50YXBMZWFmU2NyaXB0Py5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGFwTGVhZlNjcmlwdCBpcyByZXF1aXJlZCBmb3IgcDJ0ciBzY3JpcHQgcGF0aCcpO1xuICAgIH1cbiAgICBjb25zdCBwdWJrZXkgPSB0b1hPbmx5UHVibGljS2V5KHNpZ25lci5wdWJsaWNLZXkpO1xuICAgIGlmIChpbnB1dC50YXBMZWFmU2NyaXB0Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPbmx5IG9uZSBsZWFmIHNjcmlwdCBzdXBwb3J0ZWQgZm9yIHNpZ25pbmcnKTtcbiAgICB9XG4gICAgY29uc3QgW3RhcExlYWZTY3JpcHRdID0gaW5wdXQudGFwTGVhZlNjcmlwdDtcblxuICAgIGlmICh0aGlzLmlzTXVsdGlzaWdUYXByb290U2NyaXB0KHRhcExlYWZTY3JpcHQuc2NyaXB0KSkge1xuICAgICAgY29uc3QgcHViS2V5cyA9IHBhcnNlUHViU2NyaXB0Mk9mMyh0YXBMZWFmU2NyaXB0LnNjcmlwdCwgJ3RhcHJvb3RTY3JpcHRQYXRoU3BlbmQnKS5wdWJsaWNLZXlzO1xuICAgICAgYXNzZXJ0KFxuICAgICAgICBwdWJLZXlzLmZpbmQoKHBrKSA9PiBwdWJrZXkuZXF1YWxzKHBrKSksXG4gICAgICAgICdwdWJsaWMga2V5IG5vdCBmb3VuZCBpbiB0YXAgbGVhZiBzY3JpcHQnXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZENvbnRyb2xCbG9jayA9IHRhcHJvb3QucGFyc2VDb250cm9sQmxvY2soZWNjTGliLCB0YXBMZWFmU2NyaXB0LmNvbnRyb2xCbG9jayk7XG4gICAgY29uc3QgeyBsZWFmVmVyc2lvbiB9ID0gcGFyc2VkQ29udHJvbEJsb2NrO1xuICAgIGlmIChsZWFmVmVyc2lvbiAhPT0gdGFwTGVhZlNjcmlwdC5sZWFmVmVyc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUYXAgc2NyaXB0IGxlYWYgdmVyc2lvbiBtaXNtYXRjaCB3aXRoIGNvbnRyb2wgYmxvY2snKTtcbiAgICB9XG4gICAgY29uc3QgbGVhZkhhc2ggPSB0YXByb290LmdldFRhcGxlYWZIYXNoKGVjY0xpYiwgcGFyc2VkQ29udHJvbEJsb2NrLCB0YXBMZWFmU2NyaXB0LnNjcmlwdCk7XG4gICAgaWYgKCFsZWFmSGFzaGVzLmZpbmQoKGwpID0+IGwuZXF1YWxzKGxlYWZIYXNoKSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU2lnbmVyIGNhbm5vdCBzaWduIGZvciBsZWFmIGhhc2ggJHtsZWFmSGFzaC50b1N0cmluZygnaGV4Jyl9YCk7XG4gICAgfVxuICAgIGNvbnN0IHsgaGFzaCwgc2lnaGFzaFR5cGUgfSA9IHRoaXMuZ2V0VGFwcm9vdEhhc2hGb3JTaWcoaW5wdXRJbmRleCwgc2lnaGFzaFR5cGVzLCBsZWFmSGFzaCk7XG4gICAgbGV0IHNpZ25hdHVyZSA9IHNpZ25lci5zaWduU2Nobm9ycihoYXNoKTtcbiAgICBpZiAoc2lnaGFzaFR5cGUgIT09IFRyYW5zYWN0aW9uLlNJR0hBU0hfREVGQVVMVCkge1xuICAgICAgc2lnbmF0dXJlID0gQnVmZmVyLmNvbmNhdChbc2lnbmF0dXJlLCBCdWZmZXIub2Yoc2lnaGFzaFR5cGUpXSk7XG4gICAgfVxuICAgIHRoaXMuZGF0YS51cGRhdGVJbnB1dChpbnB1dEluZGV4LCB7XG4gICAgICB0YXBTY3JpcHRTaWc6IFtcbiAgICAgICAge1xuICAgICAgICAgIHB1YmtleSxcbiAgICAgICAgICBzaWduYXR1cmUsXG4gICAgICAgICAgbGVhZkhhc2gsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUYXByb290T3V0cHV0U2NyaXB0KGlucHV0SW5kZXg6IG51bWJlcikge1xuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdD8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGFwcm9vdC5jcmVhdGVUYXByb290T3V0cHV0U2NyaXB0KHtcbiAgICAgICAgY29udHJvbEJsb2NrOiBpbnB1dC50YXBMZWFmU2NyaXB0WzBdLmNvbnRyb2xCbG9jayxcbiAgICAgICAgbGVhZlNjcmlwdDogaW5wdXQudGFwTGVhZlNjcmlwdFswXS5zY3JpcHQsXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGlucHV0LnRhcEludGVybmFsS2V5ICYmIGlucHV0LnRhcE1lcmtsZVJvb3QpIHtcbiAgICAgIHJldHVybiB0YXByb290LmNyZWF0ZVRhcHJvb3RPdXRwdXRTY3JpcHQoe1xuICAgICAgICBpbnRlcm5hbFB1YktleTogaW5wdXQudGFwSW50ZXJuYWxLZXksXG4gICAgICAgIHRhcHRyZWVSb290OiBpbnB1dC50YXBNZXJrbGVSb290LFxuICAgICAgfSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignbm90IGEgdGFwcm9vdCBpbnB1dCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUYXByb290SGFzaEZvclNpZyhcbiAgICBpbnB1dEluZGV4OiBudW1iZXIsXG4gICAgc2lnaGFzaFR5cGVzPzogbnVtYmVyW10sXG4gICAgbGVhZkhhc2g/OiBCdWZmZXJcbiAgKToge1xuICAgIGhhc2g6IEJ1ZmZlcjtcbiAgICBzaWdoYXNoVHlwZTogbnVtYmVyO1xuICB9IHtcbiAgICBpZiAoIXRoaXMuaXNUYXByb290SW5wdXQoaW5wdXRJbmRleCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbm90IGEgdGFwcm9vdCBpbnB1dCcpO1xuICAgIH1cbiAgICBjb25zdCBzaWdoYXNoVHlwZSA9IHRoaXMuZGF0YS5pbnB1dHNbaW5wdXRJbmRleF0uc2lnaGFzaFR5cGUgfHwgVHJhbnNhY3Rpb24uU0lHSEFTSF9ERUZBVUxUO1xuICAgIGlmIChzaWdoYXNoVHlwZXMgJiYgc2lnaGFzaFR5cGVzLmluZGV4T2Yoc2lnaGFzaFR5cGUpIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgU2lnaGFzaCB0eXBlIGlzIG5vdCBhbGxvd2VkLiBSZXRyeSB0aGUgc2lnbiBtZXRob2QgcGFzc2luZyB0aGUgYCArXG4gICAgICAgICAgYHNpZ2hhc2hUeXBlcyBhcnJheSBvZiB3aGl0ZWxpc3RlZCB0eXBlcy4gU2lnaGFzaCB0eXBlOiAke3NpZ2hhc2hUeXBlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IHR4SW5wdXRzID0gdGhpcy50eElucHV0czsgLy8gVGhlc2UgYXJlIHNvbWV3aGF0IGNvc3RseSB0byBleHRyYWN0XG4gICAgY29uc3QgcHJldm91dFNjcmlwdHM6IEJ1ZmZlcltdID0gW107XG4gICAgY29uc3QgcHJldm91dFZhbHVlczogYmlnaW50W10gPSBbXTtcblxuICAgIHRoaXMuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICAgIGxldCBwcmV2b3V0O1xuICAgICAgaWYgKGlucHV0Lm5vbldpdG5lc3NVdHhvKSB7XG4gICAgICAgIC8vIFRPRE86IFRoaXMgY291bGQgYmUgY29zdGx5LCBlaXRoZXIgY2FjaGUgaXQgaGVyZSwgb3IgZmluZCBhIHdheSB0byBzaGFyZSB3aXRoIHN1cGVyXG4gICAgICAgIGNvbnN0IG5vbldpdG5lc3NVdHhvVHggPSAodGhpcy5jb25zdHJ1Y3RvciBhcyB0eXBlb2YgVXR4b1BzYnQpLnRyYW5zYWN0aW9uRnJvbUJ1ZmZlcihcbiAgICAgICAgICBpbnB1dC5ub25XaXRuZXNzVXR4byxcbiAgICAgICAgICB0aGlzLnR4Lm5ldHdvcmtcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBwcmV2b3V0SGFzaCA9IHR4SW5wdXRzW2ldLmhhc2g7XG4gICAgICAgIGNvbnN0IHV0eG9IYXNoID0gbm9uV2l0bmVzc1V0eG9UeC5nZXRIYXNoKCk7XG5cbiAgICAgICAgLy8gSWYgYSBub24td2l0bmVzcyBVVFhPIGlzIHByb3ZpZGVkLCBpdHMgaGFzaCBtdXN0IG1hdGNoIHRoZSBoYXNoIHNwZWNpZmllZCBpbiB0aGUgcHJldm91dFxuICAgICAgICBpZiAoIXByZXZvdXRIYXNoLmVxdWFscyh1dHhvSGFzaCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vbi13aXRuZXNzIFVUWE8gaGFzaCBmb3IgaW5wdXQgIyR7aX0gZG9lc24ndCBtYXRjaCB0aGUgaGFzaCBzcGVjaWZpZWQgaW4gdGhlIHByZXZvdXRgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByZXZvdXRJbmRleCA9IHR4SW5wdXRzW2ldLmluZGV4O1xuICAgICAgICBwcmV2b3V0ID0gbm9uV2l0bmVzc1V0eG9UeC5vdXRzW3ByZXZvdXRJbmRleF07XG4gICAgICB9IGVsc2UgaWYgKGlucHV0LndpdG5lc3NVdHhvKSB7XG4gICAgICAgIHByZXZvdXQgPSBpbnB1dC53aXRuZXNzVXR4bztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTmVlZCBhIFV0eG8gaW5wdXQgaXRlbSBmb3Igc2lnbmluZycpO1xuICAgICAgfVxuICAgICAgcHJldm91dFNjcmlwdHMucHVzaChwcmV2b3V0LnNjcmlwdCk7XG4gICAgICBwcmV2b3V0VmFsdWVzLnB1c2gocHJldm91dC52YWx1ZSk7XG4gICAgfSk7XG4gICAgY29uc3Qgb3V0cHV0U2NyaXB0ID0gdGhpcy5nZXRUYXByb290T3V0cHV0U2NyaXB0KGlucHV0SW5kZXgpO1xuICAgIGlmICghb3V0cHV0U2NyaXB0LmVxdWFscyhwcmV2b3V0U2NyaXB0c1tpbnB1dEluZGV4XSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgV2l0bmVzcyBzY3JpcHQgZm9yIGlucHV0ICMke2lucHV0SW5kZXh9IGRvZXNuJ3QgbWF0Y2ggdGhlIHNjcmlwdFB1YktleSBpbiB0aGUgcHJldm91dGApO1xuICAgIH1cbiAgICBjb25zdCBoYXNoID0gdGhpcy50eC5oYXNoRm9yV2l0bmVzc1YxKGlucHV0SW5kZXgsIHByZXZvdXRTY3JpcHRzLCBwcmV2b3V0VmFsdWVzLCBzaWdoYXNoVHlwZSwgbGVhZkhhc2gpO1xuICAgIHJldHVybiB7IGhhc2gsIHNpZ2hhc2hUeXBlIH07XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSB0aGUgbmV3IG1ldGhvZCBhZGRQcm9wcmlldGFyeUtleVZhbHMocHNidCwgZW50cnksIGluZGV4LCBrZXlWYWx1ZURhdGEpXG4gICAqXG4gICAqIEFkZHMgcHJvcHJpZXRhcnkga2V5IHZhbHVlIHBhaXIgdG8gUFNCVCBpbnB1dC5cbiAgICogRGVmYXVsdCBpZGVudGlmaWVyRW5jb2RpbmcgaXMgdXRmLTggZm9yIGlkZW50aWZpZXIuXG4gICAqL1xuICBhZGRQcm9wcmlldGFyeUtleVZhbFRvSW5wdXQoaW5wdXRJbmRleDogbnVtYmVyLCBrZXlWYWx1ZURhdGE6IFByb3ByaWV0YXJ5S2V5VmFsdWUpOiB0aGlzIHtcbiAgICByZXR1cm4gdGhpcy5hZGRVbmtub3duS2V5VmFsVG9JbnB1dChpbnB1dEluZGV4LCB7XG4gICAgICBrZXk6IGVuY29kZVByb3ByaWV0YXJ5S2V5KGtleVZhbHVlRGF0YS5rZXkpLFxuICAgICAgdmFsdWU6IGtleVZhbHVlRGF0YS52YWx1ZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlIHRoZSBuZXcgbWV0aG9kIGFkZFByb3ByaWV0YXJ5S2V5VmFsdWVzVG9Vbmtub3duS2V5VmFsdWVzKHBzYnQsIGVudHJ5LCBpbmRleCwga2V5VmFsdWVEYXRhKVxuICAgKiAgb3IgdXBkYXRlUHJvcHJpZXRhcnlLZXlWYWx1ZXNUb1Vua25vd25LZXlWYWx1ZXMoa2V5VmFsdWVEYXRhKVxuICAgKlxuICAgKiBBZGRzIG9yIHVwZGF0ZXMgKGlmIGV4aXN0cykgcHJvcHJpZXRhcnkga2V5IHZhbHVlIHBhaXIgdG8gUFNCVCBpbnB1dC5cbiAgICogRGVmYXVsdCBpZGVudGlmaWVyRW5jb2RpbmcgaXMgdXRmLTggZm9yIGlkZW50aWZpZXIuXG4gICAqL1xuICBhZGRPclVwZGF0ZVByb3ByaWV0YXJ5S2V5VmFsVG9JbnB1dChpbnB1dEluZGV4OiBudW1iZXIsIGtleVZhbHVlRGF0YTogUHJvcHJpZXRhcnlLZXlWYWx1ZSk6IHRoaXMge1xuICAgIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dCh0aGlzLmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgICBjb25zdCBrZXkgPSBlbmNvZGVQcm9wcmlldGFyeUtleShrZXlWYWx1ZURhdGEua2V5KTtcbiAgICBjb25zdCB7IHZhbHVlIH0gPSBrZXlWYWx1ZURhdGE7XG4gICAgaWYgKGlucHV0LnVua25vd25LZXlWYWxzPy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHVrdkluZGV4ID0gaW5wdXQudW5rbm93bktleVZhbHMuZmluZEluZGV4KCh1a3YpID0+IHVrdi5rZXkuZXF1YWxzKGtleSkpO1xuICAgICAgaWYgKHVrdkluZGV4ID4gLTEpIHtcbiAgICAgICAgaW5wdXQudW5rbm93bktleVZhbHNbdWt2SW5kZXhdID0geyBrZXksIHZhbHVlIH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmFkZFVua25vd25LZXlWYWxUb0lucHV0KGlucHV0SW5kZXgsIHtcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2UgZ2V0UHJvcHJpZXRhcnlLZXlWYWx1ZXNGcm9tVW5rbm93bktleVZhbHVlcyhwc2J0RmllbGQsIGtleVNlYXJjaCkuIFRoZSBuZXcgbWV0aG9kXG4gICAqIGFsbG93cyBmb3IgdGhlIHJldHJpZXZhbCBvZiBlaXRoZXIgaW5wdXQgb3Igb3V0cHV0IHByb3ByaWV0YXJ5IGtleSB2YWx1ZXMuXG4gICAqXG4gICAqIFRvIHNlYXJjaCBhbnkgZGF0YSBmcm9tIHByb3ByaWV0YXJ5IGtleSB2YWx1ZSBhZ2FpbnN0IGtleWRhdGEgaW4gdGhlIGlucHV0cy5cbiAgICogRGVmYXVsdCBpZGVudGlmaWVyRW5jb2RpbmcgaXMgdXRmLTggZm9yIGlkZW50aWZpZXIuXG4gICAqL1xuICBnZXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXRJbmRleDogbnVtYmVyLCBrZXlTZWFyY2g/OiBQcm9wcmlldGFyeUtleVNlYXJjaCk6IFByb3ByaWV0YXJ5S2V5VmFsdWVbXSB7XG4gICAgY29uc3QgaW5wdXQgPSBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIHJldHVybiBnZXRQc2J0SW5wdXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXQsIGtleVNlYXJjaCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBkZWxldGVQcm9wcmlldGFyeUtleVZhbHVlcyh0eXBlLCBpbmRleCwga2V5c1RvRGVsZXRlPykuIFRoZSBuZXcgbWV0aG9kXG4gICAqIGFsbG93cyBmb3IgdGhlIGRlbGV0aW9uIG9mIGVpdGhlciBpbnB1dCBvciBvdXRwdXQgcHJvcHJpZXRhcnkga2V5IHZhbHVlcy5cbiAgICpcbiAgICogVG8gZGVsZXRlIGFueSBkYXRhIGZyb20gcHJvcHJpZXRhcnkga2V5IHZhbHVlIGluIFBTQlQgaW5wdXQuXG4gICAqIERlZmF1bHQgaWRlbnRpZmllckVuY29kaW5nIGlzIHV0Zi04IGZvciBpZGVudGlmaWVyLlxuICAgKi9cbiAgZGVsZXRlUHJvcHJpZXRhcnlLZXlWYWxzKGlucHV0SW5kZXg6IG51bWJlciwga2V5c1RvRGVsZXRlPzogUHJvcHJpZXRhcnlLZXlTZWFyY2gpOiB0aGlzIHtcbiAgICBjb25zdCBpbnB1dCA9IGNoZWNrRm9ySW5wdXQodGhpcy5kYXRhLmlucHV0cywgaW5wdXRJbmRleCk7XG4gICAgaWYgKCFpbnB1dC51bmtub3duS2V5VmFscz8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgaWYgKGtleXNUb0RlbGV0ZSAmJiBrZXlzVG9EZWxldGUuc3VidHlwZSA9PT0gdW5kZWZpbmVkICYmIEJ1ZmZlci5pc0J1ZmZlcihrZXlzVG9EZWxldGUua2V5ZGF0YSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBwcm9wcmlldGFyeSBrZXkgc2VhcmNoIGZpbHRlciBjb21iaW5hdGlvbi4gc3VidHlwZSBpcyByZXF1aXJlZCcpO1xuICAgIH1cbiAgICBpbnB1dC51bmtub3duS2V5VmFscyA9IGlucHV0LnVua25vd25LZXlWYWxzLmZpbHRlcigoa2V5VmFsdWUsIGkpID0+IHtcbiAgICAgIGNvbnN0IGtleSA9IGRlY29kZVByb3ByaWV0YXJ5S2V5KGtleVZhbHVlLmtleSk7XG4gICAgICByZXR1cm4gIShcbiAgICAgICAga2V5c1RvRGVsZXRlID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgKGtleXNUb0RlbGV0ZS5pZGVudGlmaWVyID09PSBrZXkuaWRlbnRpZmllciAmJlxuICAgICAgICAgIChrZXlzVG9EZWxldGUuc3VidHlwZSA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICAoa2V5c1RvRGVsZXRlLnN1YnR5cGUgPT09IGtleS5zdWJ0eXBlICYmXG4gICAgICAgICAgICAgICghQnVmZmVyLmlzQnVmZmVyKGtleXNUb0RlbGV0ZS5rZXlkYXRhKSB8fCBrZXlzVG9EZWxldGUua2V5ZGF0YS5lcXVhbHMoa2V5LmtleWRhdGEpKSkpKVxuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlTXVzaWcyTm9uY2VGb3JJbnB1dChcbiAgICBpbnB1dEluZGV4OiBudW1iZXIsXG4gICAga2V5UGFpcjogQklQMzJJbnRlcmZhY2UsXG4gICAga2V5VHlwZTogJ3Jvb3QnIHwgJ2Rlcml2ZWQnLFxuICAgIHBhcmFtczogeyBzZXNzaW9uSWQ/OiBCdWZmZXI7IGRldGVybWluaXN0aWM/OiBib29sZWFuIH0gPSB7IGRldGVybWluaXN0aWM6IGZhbHNlIH1cbiAgKTogUHNidE11c2lnMlB1Yk5vbmNlIHtcbiAgICBjb25zdCBpbnB1dCA9IHRoaXMuZGF0YS5pbnB1dHNbaW5wdXRJbmRleF07XG4gICAgaWYgKCFpbnB1dC50YXBJbnRlcm5hbEtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXBJbnRlcm5hbEtleSBpcyByZXF1aXJlZCB0byBjcmVhdGUgbm9uY2UnKTtcbiAgICB9XG4gICAgaWYgKCFpbnB1dC50YXBNZXJrbGVSb290KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcE1lcmtsZVJvb3QgaXMgcmVxdWlyZWQgdG8gY3JlYXRlIG5vbmNlJyk7XG4gICAgfVxuICAgIGNvbnN0IGdldERlcml2ZWRLZXlQYWlyID0gKCk6IEJJUDMySW50ZXJmYWNlID0+IHtcbiAgICAgIGlmICghaW5wdXQudGFwQmlwMzJEZXJpdmF0aW9uPy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXBCaXAzMkRlcml2YXRpb24gaXMgcmVxdWlyZWQgdG8gY3JlYXRlIG5vbmNlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBkZXJpdmVkID0gVXR4b1BzYnQuZGVyaXZlS2V5UGFpcihrZXlQYWlyLCBpbnB1dC50YXBCaXAzMkRlcml2YXRpb24sIHsgaWdub3JlWTogdHJ1ZSB9KTtcbiAgICAgIGlmICghZGVyaXZlZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGJpcDMyRGVyaXZhdGlvbiBtYXN0ZXJGaW5nZXJwcmludCBtYXRjaGVkIHRoZSBIRCBrZXlQYWlyIGZpbmdlcnByaW50Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGVyaXZlZDtcbiAgICB9O1xuICAgIGNvbnN0IGRlcml2ZWRLZXlQYWlyID0ga2V5VHlwZSA9PT0gJ3Jvb3QnID8gZ2V0RGVyaXZlZEtleVBhaXIoKSA6IGtleVBhaXI7XG4gICAgaWYgKCFkZXJpdmVkS2V5UGFpci5wcml2YXRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByaXZhdGVLZXkgaXMgcmVxdWlyZWQgdG8gY3JlYXRlIG5vbmNlJyk7XG4gICAgfVxuICAgIGNvbnN0IHBhcnRpY2lwYW50cyA9IHBhcnNlUHNidE11c2lnMlBhcnRpY2lwYW50cyhpbnB1dCk7XG4gICAgaWYgKCFwYXJ0aWNpcGFudHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm91bmQgMCBtYXRjaGluZyBwYXJ0aWNpcGFudCBrZXkgdmFsdWUgaW5zdGVhZCBvZiAxYCk7XG4gICAgfVxuICAgIGFzc2VydFBzYnRNdXNpZzJQYXJ0aWNpcGFudHMocGFydGljaXBhbnRzLCBpbnB1dC50YXBJbnRlcm5hbEtleSwgaW5wdXQudGFwTWVya2xlUm9vdCk7XG4gICAgY29uc3QgeyB0YXBPdXRwdXRLZXksIHBhcnRpY2lwYW50UHViS2V5cyB9ID0gcGFydGljaXBhbnRzO1xuXG4gICAgY29uc3QgcGFydGljaXBhbnRQdWJLZXkgPSBwYXJ0aWNpcGFudFB1YktleXMuZmluZCgocHViS2V5KSA9PlxuICAgICAgZXF1YWxQdWJsaWNLZXlJZ25vcmVZKHB1YktleSwgZGVyaXZlZEtleVBhaXIucHVibGljS2V5KVxuICAgICk7XG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIocGFydGljaXBhbnRQdWJLZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhcnRpY2lwYW50IHBsYWluIHB1YiBrZXkgc2hvdWxkIG1hdGNoIG9uZSBiaXAzMkRlcml2YXRpb24gcGxhaW4gcHViIGtleScpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgaGFzaCB9ID0gdGhpcy5nZXRUYXByb290SGFzaEZvclNpZyhpbnB1dEluZGV4KTtcblxuICAgIGxldCBwdWJOb25jZTogQnVmZmVyO1xuICAgIGlmIChwYXJhbXMuZGV0ZXJtaW5pc3RpYykge1xuICAgICAgaWYgKHBhcmFtcy5zZXNzaW9uSWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIGV4dHJhIGVudHJvcHkgd2hlbiBnZW5lcmF0aW5nIGEgZGV0ZXJtaW5pc3RpYyBub25jZScpO1xuICAgICAgfVxuICAgICAgLy8gVGhlcmUgbXVzdCBiZSBvbmx5IDIgcGFydGljaXBhbnQgcHViS2V5cyBpZiBpdCBnb3QgdG8gdGhpcyBwb2ludFxuICAgICAgaWYgKCFlcXVhbFB1YmxpY0tleUlnbm9yZVkocGFydGljaXBhbnRQdWJLZXksIHBhcnRpY2lwYW50UHViS2V5c1sxXSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBPbmx5IHRoZSBjb3NpZ25lcidzIG5vbmNlIGNhbiBiZSBzZXQgZGV0ZXJtaW5pc3RpY2FsbHlgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5vbmNlcyA9IHBhcnNlUHNidE11c2lnMk5vbmNlcyhpbnB1dCk7XG4gICAgICBpZiAoIW5vbmNlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIG5vbmNlcyBmb3VuZCBvbiBpbnB1dCAjJHtpbnB1dEluZGV4fWApO1xuICAgICAgfVxuICAgICAgaWYgKG5vbmNlcy5sZW5ndGggPiAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGhhdmUgbW9yZSB0aGFuIDIgbm9uY2VzYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBmaXJzdFNpZ25lck5vbmNlID0gbm9uY2VzLmZpbmQoKGt2KSA9PiBlcXVhbFB1YmxpY0tleUlnbm9yZVkoa3YucGFydGljaXBhbnRQdWJLZXksIHBhcnRpY2lwYW50UHViS2V5c1swXSkpO1xuICAgICAgaWYgKCFmaXJzdFNpZ25lck5vbmNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc2lnbmVyIG5vbmNlIG11c3QgYmUgc2V0IGlmIGNvc2lnbmVyIG5vbmNlIGlzIHRvIGJlIGRlcml2ZWQgZGV0ZXJtaW5pc3RpY2FsbHknKTtcbiAgICAgIH1cblxuICAgICAgcHViTm9uY2UgPSBjcmVhdGVNdXNpZzJEZXRlcm1pbmlzdGljTm9uY2Uoe1xuICAgICAgICBwcml2YXRlS2V5OiBkZXJpdmVkS2V5UGFpci5wcml2YXRlS2V5LFxuICAgICAgICBvdGhlck5vbmNlOiBmaXJzdFNpZ25lck5vbmNlLnB1Yk5vbmNlLFxuICAgICAgICBwdWJsaWNLZXlzOiBwYXJ0aWNpcGFudFB1YktleXMsXG4gICAgICAgIGludGVybmFsUHViS2V5OiBpbnB1dC50YXBJbnRlcm5hbEtleSxcbiAgICAgICAgdGFwVHJlZVJvb3Q6IGlucHV0LnRhcE1lcmtsZVJvb3QsXG4gICAgICAgIGhhc2gsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHViTm9uY2UgPSBCdWZmZXIuZnJvbShcbiAgICAgICAgdGhpcy5ub25jZVN0b3JlLmNyZWF0ZU11c2lnMk5vbmNlKFxuICAgICAgICAgIGRlcml2ZWRLZXlQYWlyLnByaXZhdGVLZXksXG4gICAgICAgICAgcGFydGljaXBhbnRQdWJLZXksXG4gICAgICAgICAgdGFwT3V0cHV0S2V5LFxuICAgICAgICAgIGhhc2gsXG4gICAgICAgICAgcGFyYW1zLnNlc3Npb25JZFxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB7IHRhcE91dHB1dEtleSwgcGFydGljaXBhbnRQdWJLZXksIHB1Yk5vbmNlIH07XG4gIH1cblxuICBwcml2YXRlIHNldE11c2lnMk5vbmNlc0lubmVyKFxuICAgIGtleVBhaXI6IEJJUDMySW50ZXJmYWNlLFxuICAgIGtleVR5cGU6ICdyb290JyB8ICdkZXJpdmVkJyxcbiAgICBpbnB1dEluZGV4PzogbnVtYmVyLFxuICAgIHBhcmFtczogeyBzZXNzaW9uSWQ/OiBCdWZmZXI7IGRldGVybWluaXN0aWM/OiBib29sZWFuIH0gPSB7IGRldGVybWluaXN0aWM6IGZhbHNlIH1cbiAgKTogdGhpcyB7XG4gICAgaWYgKGtleVBhaXIuaXNOZXV0ZXJlZCgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByaXZhdGUga2V5IGlzIHJlcXVpcmVkIHRvIGdlbmVyYXRlIG5vbmNlJyk7XG4gICAgfVxuICAgIGlmIChCdWZmZXIuaXNCdWZmZXIocGFyYW1zLnNlc3Npb25JZCkgJiYgcGFyYW1zLnNlc3Npb25JZC5sZW5ndGggIT09IDMyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc2Vzc2lvbklkIHNpemUgJHtwYXJhbXMuc2Vzc2lvbklkLmxlbmd0aH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dEluZGV4ZXMgPSBpbnB1dEluZGV4ID09PSB1bmRlZmluZWQgPyBbLi4uQXJyYXkodGhpcy5pbnB1dENvdW50KS5rZXlzKCldIDogW2lucHV0SW5kZXhdO1xuICAgIGlucHV0SW5kZXhlcy5mb3JFYWNoKChpbmRleCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLmlzVGFwcm9vdEtleVBhdGhJbnB1dChpbmRleCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3Qgbm9uY2UgPSB0aGlzLmNyZWF0ZU11c2lnMk5vbmNlRm9ySW5wdXQoaW5kZXgsIGtleVBhaXIsIGtleVR5cGUsIHBhcmFtcyk7XG4gICAgICB0aGlzLmFkZE9yVXBkYXRlUHJvcHJpZXRhcnlLZXlWYWxUb0lucHV0KGluZGV4LCBlbmNvZGVQc2J0TXVzaWcyUHViTm9uY2Uobm9uY2UpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYW5kIHNldHMgTXVTaWcyIG5vbmNlIHRvIHRhcHJvb3Qga2V5IHBhdGggaW5wdXQgYXQgaW5wdXRJbmRleC5cbiAgICogSWYgaW5wdXQgaXMgbm90IGEgdGFwcm9vdCBrZXkgcGF0aCwgbm8gYWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gaW5wdXRJbmRleCBpbnB1dCBpbmRleFxuICAgKiBAcGFyYW0ga2V5UGFpciBkZXJpdmVkIGtleSBwYWlyXG4gICAqIEBwYXJhbSBzZXNzaW9uSWQgT3B0aW9uYWwgZXh0cmEgZW50cm9weS4gSWYgcHJvdmlkZWQgaXQgbXVzdCBlaXRoZXIgYmUgYSBjb3VudGVyIHVuaXF1ZSB0byB0aGlzIHNlY3JldCBrZXksXG4gICAqIChjb252ZXJ0ZWQgdG8gYW4gYXJyYXkgb2YgMzIgYnl0ZXMpLCBvciAzMiB1bmlmb3JtbHkgcmFuZG9tIGJ5dGVzLlxuICAgKiBAcGFyYW0gZGV0ZXJtaW5pc3RpYyBJZiB0cnVlLCBzZXQgdGhlIGNvc2lnbmVyIG5vbmNlIGRldGVybWluaXN0aWNhbGx5XG4gICAqL1xuICBzZXRJbnB1dE11c2lnMk5vbmNlKFxuICAgIGlucHV0SW5kZXg6IG51bWJlcixcbiAgICBkZXJpdmVkS2V5UGFpcjogQklQMzJJbnRlcmZhY2UsXG4gICAgcGFyYW1zOiB7IHNlc3Npb25JZD86IEJ1ZmZlcjsgZGV0ZXJtaW5pc3RpYz86IGJvb2xlYW4gfSA9IHsgZGV0ZXJtaW5pc3RpYzogZmFsc2UgfVxuICApOiB0aGlzIHtcbiAgICByZXR1cm4gdGhpcy5zZXRNdXNpZzJOb25jZXNJbm5lcihkZXJpdmVkS2V5UGFpciwgJ2Rlcml2ZWQnLCBpbnB1dEluZGV4LCBwYXJhbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhbmQgc2V0cyBNdVNpZzIgbm9uY2UgdG8gdGFwcm9vdCBrZXkgcGF0aCBpbnB1dCBhdCBpbnB1dEluZGV4LlxuICAgKiBJZiBpbnB1dCBpcyBub3QgYSB0YXByb290IGtleSBwYXRoLCBubyBhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBpbnB1dEluZGV4IGlucHV0IGluZGV4XG4gICAqIEBwYXJhbSBrZXlQYWlyIEhEIHJvb3Qga2V5IHBhaXJcbiAgICogQHBhcmFtIHNlc3Npb25JZCBPcHRpb25hbCBleHRyYSBlbnRyb3B5LiBJZiBwcm92aWRlZCBpdCBtdXN0IGVpdGhlciBiZSBhIGNvdW50ZXIgdW5pcXVlIHRvIHRoaXMgc2VjcmV0IGtleSxcbiAgICogKGNvbnZlcnRlZCB0byBhbiBhcnJheSBvZiAzMiBieXRlcyksIG9yIDMyIHVuaWZvcm1seSByYW5kb20gYnl0ZXMuXG4gICAqIEBwYXJhbSBkZXRlcm1pbmlzdGljIElmIHRydWUsIHNldCB0aGUgY29zaWduZXIgbm9uY2UgZGV0ZXJtaW5pc3RpY2FsbHlcbiAgICovXG4gIHNldElucHV0TXVzaWcyTm9uY2VIRChcbiAgICBpbnB1dEluZGV4OiBudW1iZXIsXG4gICAga2V5UGFpcjogQklQMzJJbnRlcmZhY2UsXG4gICAgcGFyYW1zOiB7IHNlc3Npb25JZD86IEJ1ZmZlcjsgZGV0ZXJtaW5pc3RpYz86IGJvb2xlYW4gfSA9IHsgZGV0ZXJtaW5pc3RpYzogZmFsc2UgfVxuICApOiB0aGlzIHtcbiAgICBjaGVja0ZvcklucHV0KHRoaXMuZGF0YS5pbnB1dHMsIGlucHV0SW5kZXgpO1xuICAgIHJldHVybiB0aGlzLnNldE11c2lnMk5vbmNlc0lubmVyKGtleVBhaXIsICdyb290JywgaW5wdXRJbmRleCwgcGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYW5kIHNldHMgTXVTaWcyIG5vbmNlIHRvIGFsbCB0YXByb290IGtleSBwYXRoIGlucHV0cy4gT3RoZXIgaW5wdXRzIHdpbGwgYmUgc2tpcHBlZC5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0SW5kZXggaW5wdXQgaW5kZXhcbiAgICogQHBhcmFtIGtleVBhaXIgZGVyaXZlZCBrZXkgcGFpclxuICAgKiBAcGFyYW0gc2Vzc2lvbklkIE9wdGlvbmFsIGV4dHJhIGVudHJvcHkuIElmIHByb3ZpZGVkIGl0IG11c3QgZWl0aGVyIGJlIGEgY291bnRlciB1bmlxdWUgdG8gdGhpcyBzZWNyZXQga2V5LFxuICAgKiAoY29udmVydGVkIHRvIGFuIGFycmF5IG9mIDMyIGJ5dGVzKSwgb3IgMzIgdW5pZm9ybWx5IHJhbmRvbSBieXRlcy5cbiAgICovXG4gIHNldEFsbElucHV0c011c2lnMk5vbmNlKFxuICAgIGtleVBhaXI6IEJJUDMySW50ZXJmYWNlLFxuICAgIHBhcmFtczogeyBzZXNzaW9uSWQ/OiBCdWZmZXI7IGRldGVybWluaXN0aWM/OiBib29sZWFuIH0gPSB7IGRldGVybWluaXN0aWM6IGZhbHNlIH1cbiAgKTogdGhpcyB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TXVzaWcyTm9uY2VzSW5uZXIoa2V5UGFpciwgJ2Rlcml2ZWQnLCB1bmRlZmluZWQsIHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBzZXRzIE11U2lnMiBub25jZSB0byBhbGwgdGFwcm9vdCBrZXkgcGF0aCBpbnB1dHMuIE90aGVyIGlucHV0cyB3aWxsIGJlIHNraXBwZWQuXG4gICAqXG4gICAqIEBwYXJhbSBpbnB1dEluZGV4IGlucHV0IGluZGV4XG4gICAqIEBwYXJhbSBrZXlQYWlyIEhEIHJvb3Qga2V5IHBhaXJcbiAgICogQHBhcmFtIHNlc3Npb25JZCBPcHRpb25hbCBleHRyYSBlbnRyb3B5LiBJZiBwcm92aWRlZCBpdCBtdXN0IGVpdGhlciBiZSBhIGNvdW50ZXIgdW5pcXVlIHRvIHRoaXMgc2VjcmV0IGtleSxcbiAgICogKGNvbnZlcnRlZCB0byBhbiBhcnJheSBvZiAzMiBieXRlcyksIG9yIDMyIHVuaWZvcm1seSByYW5kb20gYnl0ZXMuXG4gICAqL1xuICBzZXRBbGxJbnB1dHNNdXNpZzJOb25jZUhEKFxuICAgIGtleVBhaXI6IEJJUDMySW50ZXJmYWNlLFxuICAgIHBhcmFtczogeyBzZXNzaW9uSWQ/OiBCdWZmZXI7IGRldGVybWluaXN0aWM/OiBib29sZWFuIH0gPSB7IGRldGVybWluaXN0aWM6IGZhbHNlIH1cbiAgKTogdGhpcyB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TXVzaWcyTm9uY2VzSW5uZXIoa2V5UGFpciwgJ3Jvb3QnLCB1bmRlZmluZWQsIHBhcmFtcyk7XG4gIH1cblxuICBjbG9uZSgpOiB0aGlzIHtcbiAgICByZXR1cm4gVXR4b1BzYnQuZnJvbUJ1ZmZlcih0aGlzLnRvQnVmZmVyKCksIHsgbmV0d29yazogdGhpcy5uZXR3b3JrIH0pIGFzIHRoaXM7XG4gIH1cblxuICBleHRyYWN0VHJhbnNhY3Rpb24oZGlzYWJsZUZlZUNoZWNrID0gdHJ1ZSk6IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+IHtcbiAgICBjb25zdCB0eCA9IHN1cGVyLmV4dHJhY3RUcmFuc2FjdGlvbihkaXNhYmxlRmVlQ2hlY2spO1xuICAgIGlmICh0eCBpbnN0YW5jZW9mIFV0eG9UcmFuc2FjdGlvbikge1xuICAgICAgcmV0dXJuIHR4O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4dHJhY3RUcmFuc2FjdGlvbiBkaWQgbm90IHJldHVybiBpbnN0YWNlIG9mIFV0eG9UcmFuc2FjdGlvbicpO1xuICB9XG59XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!