PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-lib/dist/src/bitgo
Просмотр файла: Musig2.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Musig2NonceStore = void 0;
exports.encodePsbtMusig2Participants = encodePsbtMusig2Participants;
exports.encodePsbtMusig2PubNonce = encodePsbtMusig2PubNonce;
exports.encodePsbtMusig2PartialSig = encodePsbtMusig2PartialSig;
exports.decodePsbtMusig2Participants = decodePsbtMusig2Participants;
exports.decodePsbtMusig2Nonce = decodePsbtMusig2Nonce;
exports.decodePsbtMusig2PartialSig = decodePsbtMusig2PartialSig;
exports.createTapInternalKey = createTapInternalKey;
exports.createTapOutputKey = createTapOutputKey;
exports.createAggregateNonce = createAggregateNonce;
exports.createTapTweak = createTapTweak;
exports.musig2PartialSign = musig2PartialSign;
exports.musig2PartialSigVerify = musig2PartialSigVerify;
exports.musig2AggregateSigs = musig2AggregateSigs;
exports.createMusig2SigningSession = createMusig2SigningSession;
exports.parsePsbtMusig2Participants = parsePsbtMusig2Participants;
exports.parsePsbtMusig2Nonces = parsePsbtMusig2Nonces;
exports.parsePsbtMusig2PartialSigs = parsePsbtMusig2PartialSigs;
exports.assertPsbtMusig2Participants = assertPsbtMusig2Participants;
exports.assertPsbtMusig2Nonces = assertPsbtMusig2Nonces;
exports.getSigHashTypeFromSigs = getSigHashTypeFromSigs;
exports.createMusig2DeterministicNonce = createMusig2DeterministicNonce;
exports.musig2DeterministicSign = musig2DeterministicSign;
const outputScripts_1 = require("./outputScripts");
const noble_ecc_1 = require("../noble_ecc");
const taproot_1 = require("../taproot");
const index_1 = require("../index");
const PsbtUtil_1 = require("./PsbtUtil");
/**
* Because musig uses reference-equal buffers to cache nonces, we wrap it here to allow using
* nonces that are byte-equal but not reference-equal.
*/
class Musig2NonceStore {
constructor() {
this.nonces = [];
}
/**
* Get original Buffer instance for nonce (which may be a copy).
* @return byte-equal buffer that is reference-equal to what was stored earlier in createMusig2Nonce
*/
getRef(nonce) {
for (const b of this.nonces) {
if (Buffer.from(b).equals(nonce)) {
return b;
}
}
throw new Error(`unknown nonce`);
}
/**
* Creates musig2 nonce and stores buffer reference.
* tapInternalkey, tapMerkleRoot, tapBip32Derivation for rootWalletKey are required per p2trMusig2 key path input.
* Also participant keys are required from psbt proprietary key values.
* Ref: https://gist.github.com/sanket1729/4b525c6049f4d9e034d27368c49f28a6
* @param privateKey - signer private key
* @param publicKey - signer xy public key
* @param xOnlyPublicKey - tweaked aggregated key (tapOutputKey)
* @param sessionId Additional 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.
*/
createMusig2Nonce(privateKey, publicKey, xOnlyPublicKey, txHash, sessionId) {
if (txHash.length != 32) {
throw new Error(`Invalid txHash size ${txHash}`);
}
const buf = noble_ecc_1.musig.nonceGen({ secretKey: privateKey, publicKey, xOnlyPublicKey, msg: txHash, sessionId });
this.nonces.push(buf);
return buf;
}
}
exports.Musig2NonceStore = Musig2NonceStore;
/**
* Psbt proprietary key val util function for participants pub keys. SubType is 0x01
* Ref: https://gist.github.com/sanket1729/4b525c6049f4d9e034d27368c49f28a6
* @return x-only tapOutputKey||tapInternalKey as sub keydata, plain sigining participant keys as valuedata
*/
function encodePsbtMusig2Participants(participants) {
const keydata = [participants.tapOutputKey, participants.tapInternalKey].map((pubkey) => (0, outputScripts_1.checkXOnlyPublicKey)(pubkey));
const value = participants.participantPubKeys.map((pubkey) => (0, outputScripts_1.checkPlainPublicKey)(pubkey));
const key = {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTICIPANT_PUB_KEYS,
keydata: Buffer.concat(keydata),
};
return { key, value: Buffer.concat(value) };
}
/**
* Psbt proprietary key val util function for pub nonce. SubType is 0x02
* Ref: https://gist.github.com/sanket1729/4b525c6049f4d9e034d27368c49f28a6
* @return plain-participantPubKey||x-only-tapOutputKey as sub keydata, 66 bytes of 2 pub nonces as valuedata
*/
function encodePsbtMusig2PubNonce(nonce) {
if (nonce.pubNonce.length !== 66) {
throw new Error(`Invalid pubNonces length ${nonce.pubNonce.length}`);
}
const keydata = Buffer.concat([
(0, outputScripts_1.checkPlainPublicKey)(nonce.participantPubKey),
(0, outputScripts_1.checkXOnlyPublicKey)(nonce.tapOutputKey),
]);
const key = {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PUB_NONCE,
keydata,
};
return { key, value: nonce.pubNonce };
}
function encodePsbtMusig2PartialSig(partialSig) {
if (partialSig.partialSig.length !== 32 && partialSig.partialSig.length !== 33) {
throw new Error(`Invalid partialSig length ${partialSig.partialSig.length}`);
}
const keydata = Buffer.concat([
(0, outputScripts_1.checkPlainPublicKey)(partialSig.participantPubKey),
(0, outputScripts_1.checkXOnlyPublicKey)(partialSig.tapOutputKey),
]);
const key = {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG,
keydata,
};
return { key, value: partialSig.partialSig };
}
/**
* Decodes proprietary key value data for participant pub keys
* @param kv
*/
function decodePsbtMusig2Participants(kv) {
if (kv.key.identifier !== PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER ||
kv.key.subtype !== PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTICIPANT_PUB_KEYS) {
throw new Error(`Invalid identifier ${kv.key.identifier} or subtype ${kv.key.subtype} for participants pub keys`);
}
const key = kv.key.keydata;
if (key.length !== 64) {
throw new Error(`Invalid keydata size ${key.length} for participant pub keys`);
}
const value = kv.value;
if (value.length !== 66) {
throw new Error(`Invalid valuedata size ${value.length} for participant pub keys`);
}
const participantPubKeys = [value.subarray(0, 33), value.subarray(33)];
if (participantPubKeys[0].equals(participantPubKeys[1])) {
throw new Error(`Duplicate participant pub keys found`);
}
return { tapOutputKey: key.subarray(0, 32), tapInternalKey: key.subarray(32), participantPubKeys };
}
/**
* Decodes proprietary key value data for musig2 nonce
* @param kv
*/
function decodePsbtMusig2Nonce(kv) {
if (kv.key.identifier !== PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER || kv.key.subtype !== PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PUB_NONCE) {
throw new Error(`Invalid identifier ${kv.key.identifier} or subtype ${kv.key.subtype} for nonce`);
}
const key = kv.key.keydata;
if (key.length !== 65) {
throw new Error(`Invalid keydata size ${key.length} for nonce`);
}
const value = kv.value;
if (value.length !== 66) {
throw new Error(`Invalid valuedata size ${value.length} for nonce`);
}
return { participantPubKey: key.subarray(0, 33), tapOutputKey: key.subarray(33), pubNonce: value };
}
/**
* Decodes proprietary key value data for musig2 partial sig
* @param kv
*/
function decodePsbtMusig2PartialSig(kv) {
if (kv.key.identifier !== PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER ||
kv.key.subtype !== PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG) {
throw new Error(`Invalid identifier ${kv.key.identifier} or subtype ${kv.key.subtype} for partial sig`);
}
const key = kv.key.keydata;
if (key.length !== 65) {
throw new Error(`Invalid keydata size ${key.length} for partial sig`);
}
const value = kv.value;
if (value.length !== 32 && value.length !== 33) {
throw new Error(`Invalid valuedata size ${value.length} for partial sig`);
}
return { participantPubKey: key.subarray(0, 33), tapOutputKey: key.subarray(33), partialSig: value };
}
function createTapInternalKey(plainPubKeys) {
return Buffer.from(noble_ecc_1.musig.getXOnlyPubkey(noble_ecc_1.musig.keyAgg(plainPubKeys)));
}
function createTapOutputKey(internalPubKey, tapTreeRoot) {
return Buffer.from((0, taproot_1.tapTweakPubkey)(noble_ecc_1.ecc, (0, outputScripts_1.toXOnlyPublicKey)(internalPubKey), (0, outputScripts_1.checkTapMerkleRoot)(tapTreeRoot)).xOnlyPubkey);
}
function createAggregateNonce(pubNonces) {
return Buffer.from(noble_ecc_1.musig.nonceAgg(pubNonces));
}
function createTapTweak(tapInternalKey, tapMerkleRoot) {
return Buffer.from((0, taproot_1.calculateTapTweak)((0, outputScripts_1.checkXOnlyPublicKey)(tapInternalKey), (0, outputScripts_1.checkTapMerkleRoot)(tapMerkleRoot)));
}
function startMusig2SigningSession(aggNonce, hash, publicKeys, tweak) {
return noble_ecc_1.musig.startSigningSession(aggNonce, hash, publicKeys, { tweak, xOnly: true });
}
function musig2PartialSign(privateKey, publicNonce, sessionKey, nonceStore) {
(0, outputScripts_1.checkTxHash)(Buffer.from(sessionKey.msg));
return Buffer.from(noble_ecc_1.musig.partialSign({
secretKey: privateKey,
publicNonce: nonceStore.getRef(publicNonce),
sessionKey,
}));
}
function musig2PartialSigVerify(sig, publicKey, publicNonce, sessionKey) {
(0, outputScripts_1.checkTxHash)(Buffer.from(sessionKey.msg));
return noble_ecc_1.musig.partialVerify({ sig, publicKey, publicNonce, sessionKey });
}
function musig2AggregateSigs(sigs, sessionKey) {
return Buffer.from(noble_ecc_1.musig.signAgg(sigs, sessionKey));
}
/** @return session key that can be used to reference the session later */
function createMusig2SigningSession(sessionArgs) {
(0, outputScripts_1.checkTxHash)(sessionArgs.txHash);
const aggNonce = createAggregateNonce(sessionArgs.pubNonces);
const tweak = createTapTweak(sessionArgs.internalPubKey, sessionArgs.tapTreeRoot);
return startMusig2SigningSession(aggNonce, sessionArgs.txHash, sessionArgs.pubKeys, tweak);
}
/**
* @returns psbt proprietary key for musig2 participant key value data
* If no key value exists, undefined is returned.
*/
function parsePsbtMusig2Participants(input) {
const participantsKeyVals = (0, PsbtUtil_1.getPsbtInputProprietaryKeyVals)(input, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTICIPANT_PUB_KEYS,
});
if (!participantsKeyVals.length) {
return undefined;
}
if (participantsKeyVals.length > 1) {
throw new Error(`Found ${participantsKeyVals.length} matching participant key value instead of 1`);
}
return decodePsbtMusig2Participants(participantsKeyVals[0]);
}
/**
* @returns psbt proprietary key for musig2 public nonce key value data
* If no key value exists, undefined is returned.
*/
function parsePsbtMusig2Nonces(input) {
const nonceKeyVals = (0, PsbtUtil_1.getPsbtInputProprietaryKeyVals)(input, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PUB_NONCE,
});
if (!nonceKeyVals.length) {
return undefined;
}
if (nonceKeyVals.length > 2) {
throw new Error(`Found ${nonceKeyVals.length} matching nonce key value instead of 1 or 2`);
}
return nonceKeyVals.map((kv) => decodePsbtMusig2Nonce(kv));
}
/**
* @returns psbt proprietary key for musig2 partial sig key value data
* If no key value exists, undefined is returned.
*/
function parsePsbtMusig2PartialSigs(input) {
const sigKeyVals = (0, PsbtUtil_1.getPsbtInputProprietaryKeyVals)(input, {
identifier: PsbtUtil_1.PSBT_PROPRIETARY_IDENTIFIER,
subtype: PsbtUtil_1.ProprietaryKeySubtype.MUSIG2_PARTIAL_SIG,
});
if (!sigKeyVals.length) {
return undefined;
}
if (sigKeyVals.length > 2) {
throw new Error(`Found ${sigKeyVals.length} matching partial signature key value instead of 1 or 2`);
}
return sigKeyVals.map((kv) => decodePsbtMusig2PartialSig(kv));
}
/**
* Assert musig2 participant key value data with tapInternalKey and tapMerkleRoot.
* <tapOutputKey><tapInputKey> => <participantKey1><participantKey2>
* Using tapMerkleRoot and 2 participant keys, the tapInputKey is validated and using tapMerkleRoot and tapInputKey,
* the tapOutputKey is validated.
*/
function assertPsbtMusig2Participants(participantKeyValData, tapInternalKey, tapMerkleRoot) {
(0, outputScripts_1.checkXOnlyPublicKey)(tapInternalKey);
(0, outputScripts_1.checkTapMerkleRoot)(tapMerkleRoot);
const participantPubKeys = participantKeyValData.participantPubKeys;
const internalKey = createTapInternalKey(participantPubKeys);
if (!internalKey.equals(participantKeyValData.tapInternalKey)) {
throw new Error('Invalid participants keydata tapInternalKey');
}
const outputKey = createTapOutputKey(internalKey, tapMerkleRoot);
if (!outputKey.equals(participantKeyValData.tapOutputKey)) {
throw new Error('Invalid participants keydata tapOutputKey');
}
if (!internalKey.equals(tapInternalKey)) {
throw new Error('tapInternalKey and aggregated participant pub keys does not match');
}
}
/**
* Assert musig2 public nonce key value data with participant key value data
* (refer assertPsbtMusig2ParticipantsKeyValData).
* <participantKey1><tapOutputKey> => <pubNonce1>
* <participantKey2><tapOutputKey> => <pubNonce2>
* Checks against participant keys and tapOutputKey
*/
function assertPsbtMusig2Nonces(noncesKeyValData, participantKeyValData) {
(0, outputScripts_1.checkXOnlyPublicKey)(participantKeyValData.tapOutputKey);
participantKeyValData.participantPubKeys.forEach((kv) => (0, outputScripts_1.checkPlainPublicKey)(kv));
if (participantKeyValData.participantPubKeys[0].equals(participantKeyValData.participantPubKeys[1])) {
throw new Error(`Duplicate participant pub keys found`);
}
if (noncesKeyValData.length > 2) {
throw new Error(`Invalid nonce key value count ${noncesKeyValData.length}`);
}
noncesKeyValData.forEach((nonceKv) => {
const index = participantKeyValData.participantPubKeys.findIndex((pubKey) => nonceKv.participantPubKey.equals(pubKey));
if (index < 0) {
throw new Error('Invalid nonce keydata participant pub key');
}
if (!nonceKv.tapOutputKey.equals(participantKeyValData.tapOutputKey)) {
throw new Error('Invalid nonce keydata tapOutputKey');
}
});
}
/**
* @returns Input object but sig hash type data is taken out from partialSig field.
* If sig hash type is not common for all sigs, error out, otherwise returns the modified object and single hash type.
*/
function getSigHashTypeFromSigs(partialSigs) {
if (!partialSigs.length) {
throw new Error('partialSigs array can not be empty');
}
const pSigsWithHashType = partialSigs.map((kv) => {
const { partialSig, participantPubKey, tapOutputKey } = kv;
return partialSig.length === 33
? { pSig: { partialSig: partialSig.slice(0, 32), participantPubKey, tapOutputKey }, sigHashType: partialSig[32] }
: { pSig: { partialSig, participantPubKey, tapOutputKey }, sigHashType: index_1.Transaction.SIGHASH_DEFAULT };
});
const sigHashType = pSigsWithHashType[0].sigHashType;
if (!pSigsWithHashType.every((pSig) => pSig.sigHashType === sigHashType)) {
throw new Error('signatures must use same sig hash type');
}
return { partialSigs: pSigsWithHashType.map(({ pSig }) => pSig), sigHashType };
}
function createMusig2DeterministicNonce(params) {
return Buffer.from(noble_ecc_1.musig.deterministicNonceGen({
secretKey: params.privateKey,
aggOtherNonce: noble_ecc_1.musig.nonceAgg([params.otherNonce]),
publicKeys: params.publicKeys,
tweaks: [{ tweak: createTapTweak(params.internalPubKey, params.tapTreeRoot), xOnly: true }],
msg: params.hash,
}).publicNonce);
}
function musig2DeterministicSign(params) {
const { sig, sessionKey, publicNonce } = noble_ecc_1.musig.deterministicSign({
secretKey: params.privateKey,
aggOtherNonce: noble_ecc_1.musig.nonceAgg([params.otherNonce]),
publicKeys: params.publicKeys,
tweaks: [{ tweak: createTapTweak(params.internalPubKey, params.tapTreeRoot), xOnly: true }],
msg: params.hash,
});
return { sig: Buffer.from(sig), sessionKey, publicNonce: Buffer.from(publicNonce) };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTXVzaWcyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JpdGdvL011c2lnMi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUE2R0Esb0VBU0M7QUFPRCw0REFjQztBQUVELGdFQWNDO0FBTUQsb0VBdUJDO0FBTUQsc0RBZ0JDO0FBTUQsZ0VBbUJDO0FBRUQsb0RBRUM7QUFFRCxnREFJQztBQUVELG9EQUVDO0FBRUQsd0NBRUM7QUFXRCw4Q0FjQztBQUVELHdEQVFDO0FBRUQsa0RBRUM7QUFHRCxnRUFXQztBQU1ELGtFQWVDO0FBTUQsc0RBZUM7QUFNRCxnRUFlQztBQVFELG9FQXVCQztBQVNELHdEQTBCQztBQU1ELHdEQW9CQztBQUVELHdFQVVDO0FBRUQsMERBYUM7QUFsZUQsbURBTXlCO0FBQ3pCLDRDQUEwQztBQUUxQyx3Q0FBK0Q7QUFDL0Qsb0NBQXVDO0FBRXZDLHlDQUtvQjtBQXNDcEI7OztHQUdHO0FBQ0gsTUFBYSxnQkFBZ0I7SUFBN0I7UUFDVSxXQUFNLEdBQWlCLEVBQUUsQ0FBQztJQXdDcEMsQ0FBQztJQXRDQzs7O09BR0c7SUFDSCxNQUFNLENBQUMsS0FBaUI7UUFDdEIsS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDNUIsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxPQUFPLENBQUMsQ0FBQztZQUNYLENBQUM7UUFDSCxDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILGlCQUFpQixDQUNmLFVBQXNCLEVBQ3RCLFNBQXFCLEVBQ3JCLGNBQTBCLEVBQzFCLE1BQWtCLEVBQ2xCLFNBQWtCO1FBRWxCLElBQUksTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUN4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QUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO0FBQ3RGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTZXNzaW9uS2V5IH0gZnJvbSAnQGJyYW5kb25ibGFjay9tdXNpZyc7XG5cbmltcG9ydCB7XG4gIGNoZWNrUGxhaW5QdWJsaWNLZXksXG4gIGNoZWNrVGFwTWVya2xlUm9vdCxcbiAgY2hlY2tUeEhhc2gsXG4gIGNoZWNrWE9ubHlQdWJsaWNLZXksXG4gIHRvWE9ubHlQdWJsaWNLZXksXG59IGZyb20gJy4vb3V0cHV0U2NyaXB0cyc7XG5pbXBvcnQgeyBlY2MsIG11c2lnIH0gZnJvbSAnLi4vbm9ibGVfZWNjJztcbmltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBjYWxjdWxhdGVUYXBUd2VhaywgdGFwVHdlYWtQdWJrZXkgfSBmcm9tICcuLi90YXByb290JztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgUHNidElucHV0IH0gZnJvbSAnYmlwMTc0L3NyYy9saWIvaW50ZXJmYWNlcyc7XG5pbXBvcnQge1xuICBnZXRQc2J0SW5wdXRQcm9wcmlldGFyeUtleVZhbHMsXG4gIFByb3ByaWV0YXJ5S2V5U3VidHlwZSxcbiAgUHJvcHJpZXRhcnlLZXlWYWx1ZSxcbiAgUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSLFxufSBmcm9tICcuL1BzYnRVdGlsJztcblxuLyoqXG4gKiAgUGFydGljaXBhbnQga2V5IHZhbHVlIG9iamVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQc2J0TXVzaWcyUGFydGljaXBhbnRzIHtcbiAgdGFwT3V0cHV0S2V5OiBCdWZmZXI7XG4gIHRhcEludGVybmFsS2V5OiBCdWZmZXI7XG4gIHBhcnRpY2lwYW50UHViS2V5czogVHVwbGU8QnVmZmVyPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQc2J0TXVzaWcyRGV0ZXJtaW5pc3RpY1BhcmFtcyB7XG4gIHByaXZhdGVLZXk6IEJ1ZmZlcjtcbiAgb3RoZXJOb25jZTogQnVmZmVyO1xuICBwdWJsaWNLZXlzOiBUdXBsZTxCdWZmZXI+O1xuICBpbnRlcm5hbFB1YktleTogQnVmZmVyO1xuICB0YXBUcmVlUm9vdDogQnVmZmVyO1xuICBoYXNoOiBCdWZmZXI7XG59XG5cbi8qKlxuICogIE5vbmNlIGtleSB2YWx1ZSBvYmplY3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHNidE11c2lnMlB1Yk5vbmNlIHtcbiAgcGFydGljaXBhbnRQdWJLZXk6IEJ1ZmZlcjtcbiAgdGFwT3V0cHV0S2V5OiBCdWZmZXI7XG4gIHB1Yk5vbmNlOiBCdWZmZXI7XG59XG5cbi8qKlxuICogIFBhcnRpYWwgc2lnbmF0dXJlIGtleSB2YWx1ZSBvYmplY3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHNidE11c2lnMlBhcnRpYWxTaWcge1xuICBwYXJ0aWNpcGFudFB1YktleTogQnVmZmVyO1xuICB0YXBPdXRwdXRLZXk6IEJ1ZmZlcjtcbiAgcGFydGlhbFNpZzogQnVmZmVyO1xufVxuXG4vKipcbiAqIEJlY2F1c2UgbXVzaWcgdXNlcyByZWZlcmVuY2UtZXF1YWwgYnVmZmVycyB0byBjYWNoZSBub25jZXMsIHdlIHdyYXAgaXQgaGVyZSB0byBhbGxvdyB1c2luZ1xuICogbm9uY2VzIHRoYXQgYXJlIGJ5dGUtZXF1YWwgYnV0IG5vdCByZWZlcmVuY2UtZXF1YWwuXG4gKi9cbmV4cG9ydCBjbGFzcyBNdXNpZzJOb25jZVN0b3JlIHtcbiAgcHJpdmF0ZSBub25jZXM6IFVpbnQ4QXJyYXlbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBHZXQgb3JpZ2luYWwgQnVmZmVyIGluc3RhbmNlIGZvciBub25jZSAod2hpY2ggbWF5IGJlIGEgY29weSkuXG4gICAqIEByZXR1cm4gYnl0ZS1lcXVhbCBidWZmZXIgdGhhdCBpcyByZWZlcmVuY2UtZXF1YWwgdG8gd2hhdCB3YXMgc3RvcmVkIGVhcmxpZXIgaW4gY3JlYXRlTXVzaWcyTm9uY2VcbiAgICovXG4gIGdldFJlZihub25jZTogVWludDhBcnJheSk6IFVpbnQ4QXJyYXkge1xuICAgIGZvciAoY29uc3QgYiBvZiB0aGlzLm5vbmNlcykge1xuICAgICAgaWYgKEJ1ZmZlci5mcm9tKGIpLmVxdWFscyhub25jZSkpIHtcbiAgICAgICAgcmV0dXJuIGI7XG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgdW5rbm93biBub25jZWApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgbXVzaWcyIG5vbmNlIGFuZCBzdG9yZXMgYnVmZmVyIHJlZmVyZW5jZS5cbiAgICogdGFwSW50ZXJuYWxrZXksIHRhcE1lcmtsZVJvb3QsIHRhcEJpcDMyRGVyaXZhdGlvbiBmb3Igcm9vdFdhbGxldEtleSBhcmUgcmVxdWlyZWQgcGVyIHAydHJNdXNpZzIga2V5IHBhdGggaW5wdXQuXG4gICAqIEFsc28gcGFydGljaXBhbnQga2V5cyBhcmUgcmVxdWlyZWQgZnJvbSBwc2J0IHByb3ByaWV0YXJ5IGtleSB2YWx1ZXMuXG4gICAqIFJlZjogaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vc2Fua2V0MTcyOS80YjUyNWM2MDQ5ZjRkOWUwMzRkMjczNjhjNDlmMjhhNlxuICAgKiBAcGFyYW0gcHJpdmF0ZUtleSAtIHNpZ25lciBwcml2YXRlIGtleVxuICAgKiBAcGFyYW0gcHVibGljS2V5IC0gc2lnbmVyIHh5IHB1YmxpYyBrZXlcbiAgICogQHBhcmFtIHhPbmx5UHVibGljS2V5IC0gdHdlYWtlZCBhZ2dyZWdhdGVkIGtleSAodGFwT3V0cHV0S2V5KVxuICAgKiBAcGFyYW0gc2Vzc2lvbklkIEFkZGl0aW9uYWwgZW50cm9weS4gSWYgcHJvdmlkZWQgaXQgbXVzdCBlaXRoZXIgYmUgYSBjb3VudGVyIHVuaXF1ZSB0byB0aGlzIHNlY3JldCBrZXksXG4gICAqIChjb252ZXJ0ZWQgdG8gYW4gYXJyYXkgb2YgMzIgYnl0ZXMpLCBvciAzMiB1bmlmb3JtbHkgcmFuZG9tIGJ5dGVzLlxuICAgKi9cbiAgY3JlYXRlTXVzaWcyTm9uY2UoXG4gICAgcHJpdmF0ZUtleTogVWludDhBcnJheSxcbiAgICBwdWJsaWNLZXk6IFVpbnQ4QXJyYXksXG4gICAgeE9ubHlQdWJsaWNLZXk6IFVpbnQ4QXJyYXksXG4gICAgdHhIYXNoOiBVaW50OEFycmF5LFxuICAgIHNlc3Npb25JZD86IEJ1ZmZlclxuICApOiBVaW50OEFycmF5IHtcbiAgICBpZiAodHhIYXNoLmxlbmd0aCAhPSAzMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHR4SGFzaCBzaXplICR7dHhIYXNofWApO1xuICAgIH1cbiAgICBjb25zdCBidWYgPSBtdXNpZy5ub25jZUdlbih7IHNlY3JldEtleTogcHJpdmF0ZUtleSwgcHVibGljS2V5LCB4T25seVB1YmxpY0tleSwgbXNnOiB0eEhhc2gsIHNlc3Npb25JZCB9KTtcbiAgICB0aGlzLm5vbmNlcy5wdXNoKGJ1Zik7XG4gICAgcmV0dXJuIGJ1ZjtcbiAgfVxufVxuXG4vKipcbiAqIFBzYnQgcHJvcHJpZXRhcnkga2V5IHZhbCB1dGlsIGZ1bmN0aW9uIGZvciBwYXJ0aWNpcGFudHMgcHViIGtleXMuIFN1YlR5cGUgaXMgMHgwMVxuICogUmVmOiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9zYW5rZXQxNzI5LzRiNTI1YzYwNDlmNGQ5ZTAzNGQyNzM2OGM0OWYyOGE2XG4gKiBAcmV0dXJuIHgtb25seSB0YXBPdXRwdXRLZXl8fHRhcEludGVybmFsS2V5IGFzIHN1YiBrZXlkYXRhLCBwbGFpbiBzaWdpbmluZyBwYXJ0aWNpcGFudCBrZXlzIGFzIHZhbHVlZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlUHNidE11c2lnMlBhcnRpY2lwYW50cyhwYXJ0aWNpcGFudHM6IFBzYnRNdXNpZzJQYXJ0aWNpcGFudHMpOiBQcm9wcmlldGFyeUtleVZhbHVlIHtcbiAgY29uc3Qga2V5ZGF0YSA9IFtwYXJ0aWNpcGFudHMudGFwT3V0cHV0S2V5LCBwYXJ0aWNpcGFudHMudGFwSW50ZXJuYWxLZXldLm1hcCgocHVia2V5KSA9PiBjaGVja1hPbmx5UHVibGljS2V5KHB1YmtleSkpO1xuICBjb25zdCB2YWx1ZSA9IHBhcnRpY2lwYW50cy5wYXJ0aWNpcGFudFB1YktleXMubWFwKChwdWJrZXkpID0+IGNoZWNrUGxhaW5QdWJsaWNLZXkocHVia2V5KSk7XG4gIGNvbnN0IGtleSA9IHtcbiAgICBpZGVudGlmaWVyOiBQU0JUX1BST1BSSUVUQVJZX0lERU5USUZJRVIsXG4gICAgc3VidHlwZTogUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QQVJUSUNJUEFOVF9QVUJfS0VZUyxcbiAgICBrZXlkYXRhOiBCdWZmZXIuY29uY2F0KGtleWRhdGEpLFxuICB9O1xuICByZXR1cm4geyBrZXksIHZhbHVlOiBCdWZmZXIuY29uY2F0KHZhbHVlKSB9O1xufVxuXG4vKipcbiAqIFBzYnQgcHJvcHJpZXRhcnkga2V5IHZhbCB1dGlsIGZ1bmN0aW9uIGZvciBwdWIgbm9uY2UuIFN1YlR5cGUgaXMgMHgwMlxuICogUmVmOiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9zYW5rZXQxNzI5LzRiNTI1YzYwNDlmNGQ5ZTAzNGQyNzM2OGM0OWYyOGE2XG4gKiBAcmV0dXJuIHBsYWluLXBhcnRpY2lwYW50UHViS2V5fHx4LW9ubHktdGFwT3V0cHV0S2V5IGFzIHN1YiBrZXlkYXRhLCA2NiBieXRlcyBvZiAyIHB1YiBub25jZXMgYXMgdmFsdWVkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVQc2J0TXVzaWcyUHViTm9uY2Uobm9uY2U6IFBzYnRNdXNpZzJQdWJOb25jZSk6IFByb3ByaWV0YXJ5S2V5VmFsdWUge1xuICBpZiAobm9uY2UucHViTm9uY2UubGVuZ3RoICE9PSA2Nikge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwdWJOb25jZXMgbGVuZ3RoICR7bm9uY2UucHViTm9uY2UubGVuZ3RofWApO1xuICB9XG4gIGNvbnN0IGtleWRhdGEgPSBCdWZmZXIuY29uY2F0KFtcbiAgICBjaGVja1BsYWluUHVibGljS2V5KG5vbmNlLnBhcnRpY2lwYW50UHViS2V5KSxcbiAgICBjaGVja1hPbmx5UHVibGljS2V5KG5vbmNlLnRhcE91dHB1dEtleSksXG4gIF0pO1xuICBjb25zdCBrZXkgPSB7XG4gICAgaWRlbnRpZmllcjogUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSLFxuICAgIHN1YnR5cGU6IFByb3ByaWV0YXJ5S2V5U3VidHlwZS5NVVNJRzJfUFVCX05PTkNFLFxuICAgIGtleWRhdGEsXG4gIH07XG4gIHJldHVybiB7IGtleSwgdmFsdWU6IG5vbmNlLnB1Yk5vbmNlIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVQc2J0TXVzaWcyUGFydGlhbFNpZyhwYXJ0aWFsU2lnOiBQc2J0TXVzaWcyUGFydGlhbFNpZyk6IFByb3ByaWV0YXJ5S2V5VmFsdWUge1xuICBpZiAocGFydGlhbFNpZy5wYXJ0aWFsU2lnLmxlbmd0aCAhPT0gMzIgJiYgcGFydGlhbFNpZy5wYXJ0aWFsU2lnLmxlbmd0aCAhPT0gMzMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcGFydGlhbFNpZyBsZW5ndGggJHtwYXJ0aWFsU2lnLnBhcnRpYWxTaWcubGVuZ3RofWApO1xuICB9XG4gIGNvbnN0IGtleWRhdGEgPSBCdWZmZXIuY29uY2F0KFtcbiAgICBjaGVja1BsYWluUHVibGljS2V5KHBhcnRpYWxTaWcucGFydGljaXBhbnRQdWJLZXkpLFxuICAgIGNoZWNrWE9ubHlQdWJsaWNLZXkocGFydGlhbFNpZy50YXBPdXRwdXRLZXkpLFxuICBdKTtcbiAgY29uc3Qga2V5ID0ge1xuICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICBzdWJ0eXBlOiBQcm9wcmlldGFyeUtleVN1YnR5cGUuTVVTSUcyX1BBUlRJQUxfU0lHLFxuICAgIGtleWRhdGEsXG4gIH07XG4gIHJldHVybiB7IGtleSwgdmFsdWU6IHBhcnRpYWxTaWcucGFydGlhbFNpZyB9O1xufVxuXG4vKipcbiAqIERlY29kZXMgcHJvcHJpZXRhcnkga2V5IHZhbHVlIGRhdGEgZm9yIHBhcnRpY2lwYW50IHB1YiBrZXlzXG4gKiBAcGFyYW0ga3ZcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVBzYnRNdXNpZzJQYXJ0aWNpcGFudHMoa3Y6IFByb3ByaWV0YXJ5S2V5VmFsdWUpOiBQc2J0TXVzaWcyUGFydGljaXBhbnRzIHtcbiAgaWYgKFxuICAgIGt2LmtleS5pZGVudGlmaWVyICE9PSBQU0JUX1BST1BSSUVUQVJZX0lERU5USUZJRVIgfHxcbiAgICBrdi5rZXkuc3VidHlwZSAhPT0gUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QQVJUSUNJUEFOVF9QVUJfS0VZU1xuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgaWRlbnRpZmllciAke2t2LmtleS5pZGVudGlmaWVyfSBvciBzdWJ0eXBlICR7a3Yua2V5LnN1YnR5cGV9IGZvciBwYXJ0aWNpcGFudHMgcHViIGtleXNgKTtcbiAgfVxuXG4gIGNvbnN0IGtleSA9IGt2LmtleS5rZXlkYXRhO1xuICBpZiAoa2V5Lmxlbmd0aCAhPT0gNjQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQga2V5ZGF0YSBzaXplICR7a2V5Lmxlbmd0aH0gZm9yIHBhcnRpY2lwYW50IHB1YiBrZXlzYCk7XG4gIH1cblxuICBjb25zdCB2YWx1ZSA9IGt2LnZhbHVlO1xuICBpZiAodmFsdWUubGVuZ3RoICE9PSA2Nikge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZWRhdGEgc2l6ZSAke3ZhbHVlLmxlbmd0aH0gZm9yIHBhcnRpY2lwYW50IHB1YiBrZXlzYCk7XG4gIH1cbiAgY29uc3QgcGFydGljaXBhbnRQdWJLZXlzOiBUdXBsZTxCdWZmZXI+ID0gW3ZhbHVlLnN1YmFycmF5KDAsIDMzKSwgdmFsdWUuc3ViYXJyYXkoMzMpXTtcbiAgaWYgKHBhcnRpY2lwYW50UHViS2V5c1swXS5lcXVhbHMocGFydGljaXBhbnRQdWJLZXlzWzFdKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRHVwbGljYXRlIHBhcnRpY2lwYW50IHB1YiBrZXlzIGZvdW5kYCk7XG4gIH1cblxuICByZXR1cm4geyB0YXBPdXRwdXRLZXk6IGtleS5zdWJhcnJheSgwLCAzMiksIHRhcEludGVybmFsS2V5OiBrZXkuc3ViYXJyYXkoMzIpLCBwYXJ0aWNpcGFudFB1YktleXMgfTtcbn1cblxuLyoqXG4gKiBEZWNvZGVzIHByb3ByaWV0YXJ5IGtleSB2YWx1ZSBkYXRhIGZvciBtdXNpZzIgbm9uY2VcbiAqIEBwYXJhbSBrdlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlUHNidE11c2lnMk5vbmNlKGt2OiBQcm9wcmlldGFyeUtleVZhbHVlKTogUHNidE11c2lnMlB1Yk5vbmNlIHtcbiAgaWYgKGt2LmtleS5pZGVudGlmaWVyICE9PSBQU0JUX1BST1BSSUVUQVJZX0lERU5USUZJRVIgfHwga3Yua2V5LnN1YnR5cGUgIT09IFByb3ByaWV0YXJ5S2V5U3VidHlwZS5NVVNJRzJfUFVCX05PTkNFKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGlkZW50aWZpZXIgJHtrdi5rZXkuaWRlbnRpZmllcn0gb3Igc3VidHlwZSAke2t2LmtleS5zdWJ0eXBlfSBmb3Igbm9uY2VgKTtcbiAgfVxuXG4gIGNvbnN0IGtleSA9IGt2LmtleS5rZXlkYXRhO1xuICBpZiAoa2V5Lmxlbmd0aCAhPT0gNjUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQga2V5ZGF0YSBzaXplICR7a2V5Lmxlbmd0aH0gZm9yIG5vbmNlYCk7XG4gIH1cblxuICBjb25zdCB2YWx1ZSA9IGt2LnZhbHVlO1xuICBpZiAodmFsdWUubGVuZ3RoICE9PSA2Nikge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZWRhdGEgc2l6ZSAke3ZhbHVlLmxlbmd0aH0gZm9yIG5vbmNlYCk7XG4gIH1cblxuICByZXR1cm4geyBwYXJ0aWNpcGFudFB1YktleToga2V5LnN1YmFycmF5KDAsIDMzKSwgdGFwT3V0cHV0S2V5OiBrZXkuc3ViYXJyYXkoMzMpLCBwdWJOb25jZTogdmFsdWUgfTtcbn1cblxuLyoqXG4gKiBEZWNvZGVzIHByb3ByaWV0YXJ5IGtleSB2YWx1ZSBkYXRhIGZvciBtdXNpZzIgcGFydGlhbCBzaWdcbiAqIEBwYXJhbSBrdlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlUHNidE11c2lnMlBhcnRpYWxTaWcoa3Y6IFByb3ByaWV0YXJ5S2V5VmFsdWUpOiBQc2J0TXVzaWcyUGFydGlhbFNpZyB7XG4gIGlmIChcbiAgICBrdi5rZXkuaWRlbnRpZmllciAhPT0gUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSIHx8XG4gICAga3Yua2V5LnN1YnR5cGUgIT09IFByb3ByaWV0YXJ5S2V5U3VidHlwZS5NVVNJRzJfUEFSVElBTF9TSUdcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGlkZW50aWZpZXIgJHtrdi5rZXkuaWRlbnRpZmllcn0gb3Igc3VidHlwZSAke2t2LmtleS5zdWJ0eXBlfSBmb3IgcGFydGlhbCBzaWdgKTtcbiAgfVxuXG4gIGNvbnN0IGtleSA9IGt2LmtleS5rZXlkYXRhO1xuICBpZiAoa2V5Lmxlbmd0aCAhPT0gNjUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQga2V5ZGF0YSBzaXplICR7a2V5Lmxlbmd0aH0gZm9yIHBhcnRpYWwgc2lnYCk7XG4gIH1cblxuICBjb25zdCB2YWx1ZSA9IGt2LnZhbHVlO1xuICBpZiAodmFsdWUubGVuZ3RoICE9PSAzMiAmJiB2YWx1ZS5sZW5ndGggIT09IDMzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHZhbHVlZGF0YSBzaXplICR7dmFsdWUubGVuZ3RofSBmb3IgcGFydGlhbCBzaWdgKTtcbiAgfVxuXG4gIHJldHVybiB7IHBhcnRpY2lwYW50UHViS2V5OiBrZXkuc3ViYXJyYXkoMCwgMzMpLCB0YXBPdXRwdXRLZXk6IGtleS5zdWJhcnJheSgzMyksIHBhcnRpYWxTaWc6IHZhbHVlIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUYXBJbnRlcm5hbEtleShwbGFpblB1YktleXM6IEJ1ZmZlcltdKTogQnVmZmVyIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKG11c2lnLmdldFhPbmx5UHVia2V5KG11c2lnLmtleUFnZyhwbGFpblB1YktleXMpKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUYXBPdXRwdXRLZXkoaW50ZXJuYWxQdWJLZXk6IEJ1ZmZlciwgdGFwVHJlZVJvb3Q6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShcbiAgICB0YXBUd2Vha1B1YmtleShlY2MsIHRvWE9ubHlQdWJsaWNLZXkoaW50ZXJuYWxQdWJLZXkpLCBjaGVja1RhcE1lcmtsZVJvb3QodGFwVHJlZVJvb3QpKS54T25seVB1YmtleVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQWdncmVnYXRlTm9uY2UocHViTm9uY2VzOiBUdXBsZTxCdWZmZXI+KTogQnVmZmVyIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKG11c2lnLm5vbmNlQWdnKHB1Yk5vbmNlcykpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVGFwVHdlYWsodGFwSW50ZXJuYWxLZXk6IEJ1ZmZlciwgdGFwTWVya2xlUm9vdDogQnVmZmVyKTogQnVmZmVyIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGNhbGN1bGF0ZVRhcFR3ZWFrKGNoZWNrWE9ubHlQdWJsaWNLZXkodGFwSW50ZXJuYWxLZXkpLCBjaGVja1RhcE1lcmtsZVJvb3QodGFwTWVya2xlUm9vdCkpKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRNdXNpZzJTaWduaW5nU2Vzc2lvbihcbiAgYWdnTm9uY2U6IEJ1ZmZlcixcbiAgaGFzaDogQnVmZmVyLFxuICBwdWJsaWNLZXlzOiBUdXBsZTxCdWZmZXI+LFxuICB0d2VhazogQnVmZmVyXG4pOiBTZXNzaW9uS2V5IHtcbiAgcmV0dXJuIG11c2lnLnN0YXJ0U2lnbmluZ1Nlc3Npb24oYWdnTm9uY2UsIGhhc2gsIHB1YmxpY0tleXMsIHsgdHdlYWssIHhPbmx5OiB0cnVlIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbXVzaWcyUGFydGlhbFNpZ24oXG4gIHByaXZhdGVLZXk6IEJ1ZmZlcixcbiAgcHVibGljTm9uY2U6IFVpbnQ4QXJyYXksXG4gIHNlc3Npb25LZXk6IFNlc3Npb25LZXksXG4gIG5vbmNlU3RvcmU6IE11c2lnMk5vbmNlU3RvcmVcbik6IEJ1ZmZlciB7XG4gIGNoZWNrVHhIYXNoKEJ1ZmZlci5mcm9tKHNlc3Npb25LZXkubXNnKSk7XG4gIHJldHVybiBCdWZmZXIuZnJvbShcbiAgICBtdXNpZy5wYXJ0aWFsU2lnbih7XG4gICAgICBzZWNyZXRLZXk6IHByaXZhdGVLZXksXG4gICAgICBwdWJsaWNOb25jZTogbm9uY2VTdG9yZS5nZXRSZWYocHVibGljTm9uY2UpLFxuICAgICAgc2Vzc2lvbktleSxcbiAgICB9KVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbXVzaWcyUGFydGlhbFNpZ1ZlcmlmeShcbiAgc2lnOiBCdWZmZXIsXG4gIHB1YmxpY0tleTogQnVmZmVyLFxuICBwdWJsaWNOb25jZTogQnVmZmVyLFxuICBzZXNzaW9uS2V5OiBTZXNzaW9uS2V5XG4pOiBib29sZWFuIHtcbiAgY2hlY2tUeEhhc2goQnVmZmVyLmZyb20oc2Vzc2lvbktleS5tc2cpKTtcbiAgcmV0dXJuIG11c2lnLnBhcnRpYWxWZXJpZnkoeyBzaWcsIHB1YmxpY0tleSwgcHVibGljTm9uY2UsIHNlc3Npb25LZXkgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtdXNpZzJBZ2dyZWdhdGVTaWdzKHNpZ3M6IEJ1ZmZlcltdLCBzZXNzaW9uS2V5OiBTZXNzaW9uS2V5KTogQnVmZmVyIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKG11c2lnLnNpZ25BZ2coc2lncywgc2Vzc2lvbktleSkpO1xufVxuXG4vKiogQHJldHVybiBzZXNzaW9uIGtleSB0aGF0IGNhbiBiZSB1c2VkIHRvIHJlZmVyZW5jZSB0aGUgc2Vzc2lvbiBsYXRlciAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU11c2lnMlNpZ25pbmdTZXNzaW9uKHNlc3Npb25BcmdzOiB7XG4gIHB1Yk5vbmNlczogVHVwbGU8QnVmZmVyPjtcbiAgdHhIYXNoOiBCdWZmZXI7XG4gIHB1YktleXM6IFR1cGxlPEJ1ZmZlcj47XG4gIGludGVybmFsUHViS2V5OiBCdWZmZXI7XG4gIHRhcFRyZWVSb290OiBCdWZmZXI7XG59KTogU2Vzc2lvbktleSB7XG4gIGNoZWNrVHhIYXNoKHNlc3Npb25BcmdzLnR4SGFzaCk7XG4gIGNvbnN0IGFnZ05vbmNlID0gY3JlYXRlQWdncmVnYXRlTm9uY2Uoc2Vzc2lvbkFyZ3MucHViTm9uY2VzKTtcbiAgY29uc3QgdHdlYWsgPSBjcmVhdGVUYXBUd2VhayhzZXNzaW9uQXJncy5pbnRlcm5hbFB1YktleSwgc2Vzc2lvbkFyZ3MudGFwVHJlZVJvb3QpO1xuICByZXR1cm4gc3RhcnRNdXNpZzJTaWduaW5nU2Vzc2lvbihhZ2dOb25jZSwgc2Vzc2lvbkFyZ3MudHhIYXNoLCBzZXNzaW9uQXJncy5wdWJLZXlzLCB0d2Vhayk7XG59XG5cbi8qKlxuICogQHJldHVybnMgcHNidCBwcm9wcmlldGFyeSBrZXkgZm9yIG11c2lnMiBwYXJ0aWNpcGFudCBrZXkgdmFsdWUgZGF0YVxuICogSWYgbm8ga2V5IHZhbHVlIGV4aXN0cywgdW5kZWZpbmVkIGlzIHJldHVybmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VQc2J0TXVzaWcyUGFydGljaXBhbnRzKGlucHV0OiBQc2J0SW5wdXQpOiBQc2J0TXVzaWcyUGFydGljaXBhbnRzIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcGFydGljaXBhbnRzS2V5VmFscyA9IGdldFBzYnRJbnB1dFByb3ByaWV0YXJ5S2V5VmFscyhpbnB1dCwge1xuICAgIGlkZW50aWZpZXI6IFBTQlRfUFJPUFJJRVRBUllfSURFTlRJRklFUixcbiAgICBzdWJ0eXBlOiBQcm9wcmlldGFyeUtleVN1YnR5cGUuTVVTSUcyX1BBUlRJQ0lQQU5UX1BVQl9LRVlTLFxuICB9KTtcblxuICBpZiAoIXBhcnRpY2lwYW50c0tleVZhbHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlmIChwYXJ0aWNpcGFudHNLZXlWYWxzLmxlbmd0aCA+IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZvdW5kICR7cGFydGljaXBhbnRzS2V5VmFscy5sZW5ndGh9IG1hdGNoaW5nIHBhcnRpY2lwYW50IGtleSB2YWx1ZSBpbnN0ZWFkIG9mIDFgKTtcbiAgfVxuXG4gIHJldHVybiBkZWNvZGVQc2J0TXVzaWcyUGFydGljaXBhbnRzKHBhcnRpY2lwYW50c0tleVZhbHNbMF0pO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHBzYnQgcHJvcHJpZXRhcnkga2V5IGZvciBtdXNpZzIgcHVibGljIG5vbmNlIGtleSB2YWx1ZSBkYXRhXG4gKiBJZiBubyBrZXkgdmFsdWUgZXhpc3RzLCB1bmRlZmluZWQgaXMgcmV0dXJuZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVBzYnRNdXNpZzJOb25jZXMoaW5wdXQ6IFBzYnRJbnB1dCk6IFBzYnRNdXNpZzJQdWJOb25jZVtdIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qgbm9uY2VLZXlWYWxzID0gZ2V0UHNidElucHV0UHJvcHJpZXRhcnlLZXlWYWxzKGlucHV0LCB7XG4gICAgaWRlbnRpZmllcjogUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSLFxuICAgIHN1YnR5cGU6IFByb3ByaWV0YXJ5S2V5U3VidHlwZS5NVVNJRzJfUFVCX05PTkNFLFxuICB9KTtcblxuICBpZiAoIW5vbmNlS2V5VmFscy5sZW5ndGgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgaWYgKG5vbmNlS2V5VmFscy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCAke25vbmNlS2V5VmFscy5sZW5ndGh9IG1hdGNoaW5nIG5vbmNlIGtleSB2YWx1ZSBpbnN0ZWFkIG9mIDEgb3IgMmApO1xuICB9XG5cbiAgcmV0dXJuIG5vbmNlS2V5VmFscy5tYXAoKGt2KSA9PiBkZWNvZGVQc2J0TXVzaWcyTm9uY2Uoa3YpKTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyBwc2J0IHByb3ByaWV0YXJ5IGtleSBmb3IgbXVzaWcyIHBhcnRpYWwgc2lnIGtleSB2YWx1ZSBkYXRhXG4gKiBJZiBubyBrZXkgdmFsdWUgZXhpc3RzLCB1bmRlZmluZWQgaXMgcmV0dXJuZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVBzYnRNdXNpZzJQYXJ0aWFsU2lncyhpbnB1dDogUHNidElucHV0KTogUHNidE11c2lnMlBhcnRpYWxTaWdbXSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHNpZ0tleVZhbHMgPSBnZXRQc2J0SW5wdXRQcm9wcmlldGFyeUtleVZhbHMoaW5wdXQsIHtcbiAgICBpZGVudGlmaWVyOiBQU0JUX1BST1BSSUVUQVJZX0lERU5USUZJRVIsXG4gICAgc3VidHlwZTogUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QQVJUSUFMX1NJRyxcbiAgfSk7XG5cbiAgaWYgKCFzaWdLZXlWYWxzLmxlbmd0aCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAoc2lnS2V5VmFscy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCAke3NpZ0tleVZhbHMubGVuZ3RofSBtYXRjaGluZyBwYXJ0aWFsIHNpZ25hdHVyZSBrZXkgdmFsdWUgaW5zdGVhZCBvZiAxIG9yIDJgKTtcbiAgfVxuXG4gIHJldHVybiBzaWdLZXlWYWxzLm1hcCgoa3YpID0+IGRlY29kZVBzYnRNdXNpZzJQYXJ0aWFsU2lnKGt2KSk7XG59XG5cbi8qKlxuICogQXNzZXJ0IG11c2lnMiBwYXJ0aWNpcGFudCBrZXkgdmFsdWUgZGF0YSB3aXRoIHRhcEludGVybmFsS2V5IGFuZCB0YXBNZXJrbGVSb290LlxuICogPHRhcE91dHB1dEtleT48dGFwSW5wdXRLZXk+ID0+IDxwYXJ0aWNpcGFudEtleTE+PHBhcnRpY2lwYW50S2V5Mj5cbiAqIFVzaW5nIHRhcE1lcmtsZVJvb3QgYW5kIDIgcGFydGljaXBhbnQga2V5cywgdGhlIHRhcElucHV0S2V5IGlzIHZhbGlkYXRlZCBhbmQgdXNpbmcgdGFwTWVya2xlUm9vdCBhbmQgdGFwSW5wdXRLZXksXG4gKiB0aGUgdGFwT3V0cHV0S2V5IGlzIHZhbGlkYXRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFBzYnRNdXNpZzJQYXJ0aWNpcGFudHMoXG4gIHBhcnRpY2lwYW50S2V5VmFsRGF0YTogUHNidE11c2lnMlBhcnRpY2lwYW50cyxcbiAgdGFwSW50ZXJuYWxLZXk6IEJ1ZmZlcixcbiAgdGFwTWVya2xlUm9vdDogQnVmZmVyXG4pOiB2b2lkIHtcbiAgY2hlY2tYT25seVB1YmxpY0tleSh0YXBJbnRlcm5hbEtleSk7XG4gIGNoZWNrVGFwTWVya2xlUm9vdCh0YXBNZXJrbGVSb290KTtcblxuICBjb25zdCBwYXJ0aWNpcGFudFB1YktleXMgPSBwYXJ0aWNpcGFudEtleVZhbERhdGEucGFydGljaXBhbnRQdWJLZXlzO1xuXG4gIGNvbnN0IGludGVybmFsS2V5ID0gY3JlYXRlVGFwSW50ZXJuYWxLZXkocGFydGljaXBhbnRQdWJLZXlzKTtcbiAgaWYgKCFpbnRlcm5hbEtleS5lcXVhbHMocGFydGljaXBhbnRLZXlWYWxEYXRhLnRhcEludGVybmFsS2V5KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwYXJ0aWNpcGFudHMga2V5ZGF0YSB0YXBJbnRlcm5hbEtleScpO1xuICB9XG5cbiAgY29uc3Qgb3V0cHV0S2V5ID0gY3JlYXRlVGFwT3V0cHV0S2V5KGludGVybmFsS2V5LCB0YXBNZXJrbGVSb290KTtcbiAgaWYgKCFvdXRwdXRLZXkuZXF1YWxzKHBhcnRpY2lwYW50S2V5VmFsRGF0YS50YXBPdXRwdXRLZXkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhcnRpY2lwYW50cyBrZXlkYXRhIHRhcE91dHB1dEtleScpO1xuICB9XG5cbiAgaWYgKCFpbnRlcm5hbEtleS5lcXVhbHModGFwSW50ZXJuYWxLZXkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0YXBJbnRlcm5hbEtleSBhbmQgYWdncmVnYXRlZCBwYXJ0aWNpcGFudCBwdWIga2V5cyBkb2VzIG5vdCBtYXRjaCcpO1xuICB9XG59XG5cbi8qKlxuICogQXNzZXJ0IG11c2lnMiBwdWJsaWMgbm9uY2Uga2V5IHZhbHVlIGRhdGEgd2l0aCBwYXJ0aWNpcGFudCBrZXkgdmFsdWUgZGF0YVxuICogKHJlZmVyIGFzc2VydFBzYnRNdXNpZzJQYXJ0aWNpcGFudHNLZXlWYWxEYXRhKS5cbiAqIDxwYXJ0aWNpcGFudEtleTE+PHRhcE91dHB1dEtleT4gPT4gPHB1Yk5vbmNlMT5cbiAqIDxwYXJ0aWNpcGFudEtleTI+PHRhcE91dHB1dEtleT4gPT4gPHB1Yk5vbmNlMj5cbiAqIENoZWNrcyBhZ2FpbnN0IHBhcnRpY2lwYW50IGtleXMgYW5kIHRhcE91dHB1dEtleVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0UHNidE11c2lnMk5vbmNlcyhcbiAgbm9uY2VzS2V5VmFsRGF0YTogUHNidE11c2lnMlB1Yk5vbmNlW10sXG4gIHBhcnRpY2lwYW50S2V5VmFsRGF0YTogUHNidE11c2lnMlBhcnRpY2lwYW50c1xuKTogdm9pZCB7XG4gIGNoZWNrWE9ubHlQdWJsaWNLZXkocGFydGljaXBhbnRLZXlWYWxEYXRhLnRhcE91dHB1dEtleSk7XG4gIHBhcnRpY2lwYW50S2V5VmFsRGF0YS5wYXJ0aWNpcGFudFB1YktleXMuZm9yRWFjaCgoa3YpID0+IGNoZWNrUGxhaW5QdWJsaWNLZXkoa3YpKTtcbiAgaWYgKHBhcnRpY2lwYW50S2V5VmFsRGF0YS5wYXJ0aWNpcGFudFB1YktleXNbMF0uZXF1YWxzKHBhcnRpY2lwYW50S2V5VmFsRGF0YS5wYXJ0aWNpcGFudFB1YktleXNbMV0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBEdXBsaWNhdGUgcGFydGljaXBhbnQgcHViIGtleXMgZm91bmRgKTtcbiAgfVxuXG4gIGlmIChub25jZXNLZXlWYWxEYXRhLmxlbmd0aCA+IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbm9uY2Uga2V5IHZhbHVlIGNvdW50ICR7bm9uY2VzS2V5VmFsRGF0YS5sZW5ndGh9YCk7XG4gIH1cblxuICBub25jZXNLZXlWYWxEYXRhLmZvckVhY2goKG5vbmNlS3YpID0+IHtcbiAgICBjb25zdCBpbmRleCA9IHBhcnRpY2lwYW50S2V5VmFsRGF0YS5wYXJ0aWNpcGFudFB1YktleXMuZmluZEluZGV4KChwdWJLZXkpID0+XG4gICAgICBub25jZUt2LnBhcnRpY2lwYW50UHViS2V5LmVxdWFscyhwdWJLZXkpXG4gICAgKTtcbiAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbm9uY2Uga2V5ZGF0YSBwYXJ0aWNpcGFudCBwdWIga2V5Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFub25jZUt2LnRhcE91dHB1dEtleS5lcXVhbHMocGFydGljaXBhbnRLZXlWYWxEYXRhLnRhcE91dHB1dEtleSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBub25jZSBrZXlkYXRhIHRhcE91dHB1dEtleScpO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQHJldHVybnMgSW5wdXQgb2JqZWN0IGJ1dCBzaWcgaGFzaCB0eXBlIGRhdGEgaXMgdGFrZW4gb3V0IGZyb20gcGFydGlhbFNpZyBmaWVsZC5cbiAqIElmIHNpZyBoYXNoIHR5cGUgaXMgbm90IGNvbW1vbiBmb3IgYWxsIHNpZ3MsIGVycm9yIG91dCwgb3RoZXJ3aXNlIHJldHVybnMgdGhlIG1vZGlmaWVkIG9iamVjdCBhbmQgc2luZ2xlIGhhc2ggdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFNpZ0hhc2hUeXBlRnJvbVNpZ3MocGFydGlhbFNpZ3M6IFBzYnRNdXNpZzJQYXJ0aWFsU2lnW10pOiB7XG4gIHBhcnRpYWxTaWdzOiBQc2J0TXVzaWcyUGFydGlhbFNpZ1tdO1xuICBzaWdIYXNoVHlwZTogbnVtYmVyO1xufSB7XG4gIGlmICghcGFydGlhbFNpZ3MubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwYXJ0aWFsU2lncyBhcnJheSBjYW4gbm90IGJlIGVtcHR5Jyk7XG4gIH1cbiAgY29uc3QgcFNpZ3NXaXRoSGFzaFR5cGUgPSBwYXJ0aWFsU2lncy5tYXAoKGt2KSA9PiB7XG4gICAgY29uc3QgeyBwYXJ0aWFsU2lnLCBwYXJ0aWNpcGFudFB1YktleSwgdGFwT3V0cHV0S2V5IH0gPSBrdjtcbiAgICByZXR1cm4gcGFydGlhbFNpZy5sZW5ndGggPT09IDMzXG4gICAgICA/IHsgcFNpZzogeyBwYXJ0aWFsU2lnOiBwYXJ0aWFsU2lnLnNsaWNlKDAsIDMyKSwgcGFydGljaXBhbnRQdWJLZXksIHRhcE91dHB1dEtleSB9LCBzaWdIYXNoVHlwZTogcGFydGlhbFNpZ1szMl0gfVxuICAgICAgOiB7IHBTaWc6IHsgcGFydGlhbFNpZywgcGFydGljaXBhbnRQdWJLZXksIHRhcE91dHB1dEtleSB9LCBzaWdIYXNoVHlwZTogVHJhbnNhY3Rpb24uU0lHSEFTSF9ERUZBVUxUIH07XG4gIH0pO1xuXG4gIGNvbnN0IHNpZ0hhc2hUeXBlID0gcFNpZ3NXaXRoSGFzaFR5cGVbMF0uc2lnSGFzaFR5cGU7XG4gIGlmICghcFNpZ3NXaXRoSGFzaFR5cGUuZXZlcnkoKHBTaWcpID0+IHBTaWcuc2lnSGFzaFR5cGUgPT09IHNpZ0hhc2hUeXBlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2lnbmF0dXJlcyBtdXN0IHVzZSBzYW1lIHNpZyBoYXNoIHR5cGUnKTtcbiAgfVxuXG4gIHJldHVybiB7IHBhcnRpYWxTaWdzOiBwU2lnc1dpdGhIYXNoVHlwZS5tYXAoKHsgcFNpZyB9KSA9PiBwU2lnKSwgc2lnSGFzaFR5cGUgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU11c2lnMkRldGVybWluaXN0aWNOb25jZShwYXJhbXM6IFBzYnRNdXNpZzJEZXRlcm1pbmlzdGljUGFyYW1zKTogQnVmZmVyIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKFxuICAgIG11c2lnLmRldGVybWluaXN0aWNOb25jZUdlbih7XG4gICAgICBzZWNyZXRLZXk6IHBhcmFtcy5wcml2YXRlS2V5LFxuICAgICAgYWdnT3RoZXJOb25jZTogbXVzaWcubm9uY2VBZ2coW3BhcmFtcy5vdGhlck5vbmNlXSksXG4gICAgICBwdWJsaWNLZXlzOiBwYXJhbXMucHVibGljS2V5cyxcbiAgICAgIHR3ZWFrczogW3sgdHdlYWs6IGNyZWF0ZVRhcFR3ZWFrKHBhcmFtcy5pbnRlcm5hbFB1YktleSwgcGFyYW1zLnRhcFRyZWVSb290KSwgeE9ubHk6IHRydWUgfV0sXG4gICAgICBtc2c6IHBhcmFtcy5oYXNoLFxuICAgIH0pLnB1YmxpY05vbmNlXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtdXNpZzJEZXRlcm1pbmlzdGljU2lnbihwYXJhbXM6IFBzYnRNdXNpZzJEZXRlcm1pbmlzdGljUGFyYW1zKToge1xuICBzaWc6IEJ1ZmZlcjtcbiAgc2Vzc2lvbktleTogU2Vzc2lvbktleTtcbiAgcHVibGljTm9uY2U6IEJ1ZmZlcjtcbn0ge1xuICBjb25zdCB7IHNpZywgc2Vzc2lvbktleSwgcHVibGljTm9uY2UgfSA9IG11c2lnLmRldGVybWluaXN0aWNTaWduKHtcbiAgICBzZWNyZXRLZXk6IHBhcmFtcy5wcml2YXRlS2V5LFxuICAgIGFnZ090aGVyTm9uY2U6IG11c2lnLm5vbmNlQWdnKFtwYXJhbXMub3RoZXJOb25jZV0pLFxuICAgIHB1YmxpY0tleXM6IHBhcmFtcy5wdWJsaWNLZXlzLFxuICAgIHR3ZWFrczogW3sgdHdlYWs6IGNyZWF0ZVRhcFR3ZWFrKHBhcmFtcy5pbnRlcm5hbFB1YktleSwgcGFyYW1zLnRhcFRyZWVSb290KSwgeE9ubHk6IHRydWUgfV0sXG4gICAgbXNnOiBwYXJhbXMuaGFzaCxcbiAgfSk7XG4gIHJldHVybiB7IHNpZzogQnVmZmVyLmZyb20oc2lnKSwgc2Vzc2lvbktleSwgcHVibGljTm9uY2U6IEJ1ZmZlci5mcm9tKHB1YmxpY05vbmNlKSB9O1xufVxuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!