UNPKG

tink-crypto

Version:

A multi-language, cross-platform library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.

148 lines 18.7 kB
/** * @license * Copyright 2022 Google LLC * SPDX-License-Identifier: Apache-2.0 */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { SecurityException } from '../../../exception/security_exception'; import * as bytes from '../../../subtle/bytes'; import * as hpkeUtil from './hpke_util'; /** * Hybrid Public Key Encryption (HPKE) context for either a sender or a * recipient. * * @see https://www.rfc-editor.org/rfc/rfc9180.html#name-creating-the-encryption-con */ export class HpkeContext { constructor(encapsulatedKey, key, baseNonce, aead) { this.encapsulatedKey = encapsulatedKey; this.key = key; this.baseNonce = baseNonce; this.aead = aead; this.sequenceNumber = BigInt(0); /** * Indicates that the message limit is reached, calculated as per * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-11. */ this.maxSequenceNumber = (BigInt(1) << BigInt(8 * this.aead.getNonceLength())) - BigInt(1); } /** * Performs AEAD encryption of `plaintext` with `associatedData` * according to `ContextS.Seal()` as defined in * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-8. */ seal(plaintext, associatedData) { return __awaiter(this, void 0, void 0, function* () { const nonce = this.computeNonceAndIncrementSequenceNumber(); return yield this.aead.seal({ key: this.key, nonce, plaintext, associatedData }); }); } /** * Performs AEAD decryption of `ciphertext` with `associatedData` * according to `ContextR.Open()` as defined in * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-10. */ open(ciphertext, associatedData) { return __awaiter(this, void 0, void 0, function* () { const nonce = this.computeNonceAndIncrementSequenceNumber(); return this.aead.open({ key: this.key, nonce, ciphertext, associatedData }); }); } /** * Computes nonce according to `ComputeNonce` as defined in * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.2-11. * for seal/open and increments the sequence number. */ computeNonceAndIncrementSequenceNumber() { const seqBytes = hpkeUtil.bigIntToByteArray(this.aead.getNonceLength(), this.sequenceNumber); const nonce = bytes.xor(this.baseNonce, seqBytes); if (this.sequenceNumber >= this.maxSequenceNumber) { throw new SecurityException('message limit reached'); } this.sequenceNumber += (BigInt(1)); return nonce; } getKey() { return this.key; } getBaseNonce() { return this.baseNonce; } getEncapsulatedKey() { return this.encapsulatedKey; } } /** Helper function factored out to facilitate unit testing. */ export function createContext(encapsulatedKey, sharedSecret, kem, kdf, aead, info) { return __awaiter(this, void 0, void 0, function* () { const suiteId = hpkeUtil.hpkeSuiteId({ kemId: kem.getKemId(), kdfId: kdf.getKdfId(), aeadId: aead.getAeadId() }); /** * The IKM values below are empty because we only support base mode * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1.9. */ const pskIdHash = yield kdf.labeledExtract({ ikm: new Uint8Array(0), ikmLabel: 'psk_id_hash', suiteId, }); const infoHash = yield kdf.labeledExtract({ ikm: info, ikmLabel: 'info_hash', suiteId, }); const keyScheduleContext = bytes.concat(hpkeUtil.BASE_MODE, pskIdHash, infoHash); const secret = yield kdf.labeledExtract({ ikm: new Uint8Array(0), ikmLabel: 'secret', suiteId, salt: sharedSecret }); const key = yield kdf.labeledExpand({ prk: secret, info: keyScheduleContext, infoLabel: 'key', suiteId, length: aead.getKeyLength() }); const baseNonce = yield kdf.labeledExpand({ prk: secret, info: keyScheduleContext, infoLabel: 'base_nonce', suiteId, length: aead.getNonceLength() }); return new HpkeContext(encapsulatedKey, key, baseNonce, aead); }); } /** * Creates HPKE sender context according to `KeySchedule` as defined in * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-9. */ export function createSenderContext(recipientPublicKey, kem, kdf, aead, info) { return __awaiter(this, void 0, void 0, function* () { const encapOutput = yield kem.encapsulate(recipientPublicKey); const encapsulatedKey = encapOutput.encapsulatedKey; const sharedSecret = encapOutput.sharedSecret; return yield createContext(encapsulatedKey, sharedSecret, kem, kdf, aead, info); }); } /** * Creates HPKE recipient context according to `KeySchedule` as defined in * @see https://www.rfc-editor.org/rfc/rfc9180.html#section-5.1-9. */ export function createRecipientContext(encapsulatedKey, recipientPrivateKey, kem, kdf, aead, info) { return __awaiter(this, void 0, void 0, function* () { const sharedSecret = yield kem.decapsulate(encapsulatedKey, recipientPrivateKey); return yield createContext(encapsulatedKey, sharedSecret, kem, kdf, aead, info); }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHBrZV9jb250ZXh0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vaHlicmlkL2ludGVybmFsL2hwa2UvaHBrZV9jb250ZXh0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7Ozs7Ozs7Ozs7QUFFSCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSx1Q0FBdUMsQ0FBQztBQUN4RSxPQUFPLEtBQUssS0FBSyxNQUFNLHVCQUF1QixDQUFDO0FBTS9DLE9BQU8sS0FBSyxRQUFRLE1BQU0sYUFBYSxDQUFDO0FBR3hDOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFJdEIsWUFDcUIsZUFBMkIsRUFDM0IsR0FBZSxFQUFtQixTQUFxQixFQUN2RCxJQUFjO1FBRmQsb0JBQWUsR0FBZixlQUFlLENBQVk7UUFDM0IsUUFBRyxHQUFILEdBQUcsQ0FBWTtRQUFtQixjQUFTLEdBQVQsU0FBUyxDQUFZO1FBQ3ZELFNBQUksR0FBSixJQUFJLENBQVU7UUFDakMsSUFBSSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFaEM7OztXQUdHO1FBQ0gsSUFBSSxDQUFDLGlCQUFpQjtZQUNsQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNHLElBQUksQ0FBQyxTQUFxQixFQUFFLGNBQTBCOztZQUUxRCxNQUFNLEtBQUssR0FBZSxJQUFJLENBQUMsc0NBQXNDLEVBQUUsQ0FBQztZQUN4RSxPQUFPLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQ3ZCLEVBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxjQUFj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IExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuXG5pbXBvcnQge1NlY3VyaXR5RXhjZXB0aW9ufSBmcm9tICcuLi8uLi8uLi9leGNlcHRpb24vc2VjdXJpdHlfZXhjZXB0aW9uJztcbmltcG9ydCAqIGFzIGJ5dGVzIGZyb20gJy4uLy4uLy4uL3N1YnRsZS9ieXRlcyc7XG5cbmltcG9ydCB7SHBrZUFlYWR9IGZyb20gJy4vaHBrZV9hZWFkJztcbmltcG9ydCB7SHBrZUtkZn0gZnJvbSAnLi9ocGtlX2tkZic7XG5pbXBvcnQge0hwa2VLZW19IGZyb20gJy4vaHBrZV9rZW0nO1xuaW1wb3J0IHtIcGtlS2VtRW5jYXBPdXRwdXR9IGZyb20gJy4vaHBrZV9rZW1fZW5jYXBfb3V0cHV0JztcbmltcG9ydCAqIGFzIGhwa2VVdGlsIGZyb20gJy4vaHBrZV91dGlsJztcbmltcG9ydCB7TmlzdEN1cnZlc0hwa2VLZW1Qcml2YXRlS2V5fSBmcm9tICcuL25pc3RfY3VydmVzX2hwa2Vfa2VtX3ByaXZhdGVfa2V5JztcblxuLyoqXG4gKiBIeWJyaWQgUHVibGljIEtleSBFbmNyeXB0aW9uIChIUEtFKSBjb250ZXh0IGZvciBlaXRoZXIgYSBzZW5kZXIgb3IgYVxuICogcmVjaXBpZW50LlxuICpcbiAqIEBzZWUgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzkxODAuaHRtbCNuYW1lLWNyZWF0aW5nLXRoZS1lbmNyeXB0aW9uLWNvblxuICovXG5leHBvcnQgY2xhc3MgSHBrZUNvbnRleHQge1xuICBwcml2YXRlIHNlcXVlbmNlTnVtYmVyOiBiaWdpbnQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWF4U2VxdWVuY2VOdW1iZXI6IGJpZ2ludDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgZW5jYXBzdWxhdGVkS2V5OiBVaW50OEFycmF5LFxuICAgICAgcHJpdmF0ZSByZWFkb25seSBrZXk6IFVpbnQ4QXJyYXksIHByaXZhdGUgcmVhZG9ubHkgYmFzZU5vbmNlOiBVaW50OEFycmF5LFxuICAgICAgcHJpdmF0ZSByZWFkb25seSBhZWFkOiBIcGtlQWVhZCkge1xuICAgIHRoaXMuc2VxdWVuY2VOdW1iZXIgPSBCaWdJbnQoMCk7XG5cbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgbWVzc2FnZSBsaW1pdCBpcyByZWFjaGVkLCBjYWxjdWxhdGVkIGFzIHBlclxuICAgICAqIEBzZWUgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzkxODAuaHRtbCNzZWN0aW9uLTUuMi0xMS5cbiAgICAgKi9cbiAgICB0aGlzLm1heFNlcXVlbmNlTnVtYmVyID1cbiAgICAgICAgKEJpZ0ludCgxKSA8PCBCaWdJbnQoOCAqIHRoaXMuYWVhZC5nZXROb25jZUxlbmd0aCgpKSkgLSBCaWdJbnQoMSk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgQUVBRCBlbmNyeXB0aW9uIG9mIGBwbGFpbnRleHRgIHdpdGggYGFzc29jaWF0ZWREYXRhYFxuICAgKiBhY2NvcmRpbmcgdG8gYENvbnRleHRTLlNlYWwoKWAgYXMgZGVmaW5lZCBpblxuICAgKiBAc2VlIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM5MTgwLmh0bWwjc2VjdGlvbi01LjItOC5cbiAgICovXG4gIGFzeW5jIHNlYWwocGxhaW50ZXh0OiBVaW50OEFycmF5LCBhc3NvY2lhdGVkRGF0YTogVWludDhBcnJheSk6XG4gICAgICBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCBub25jZTogVWludDhBcnJheSA9IHRoaXMuY29tcHV0ZU5vbmNlQW5kSW5jcmVtZW50U2VxdWVuY2VOdW1iZXIoKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5hZWFkLnNlYWwoXG4gICAgICAgIHtrZXk6IHRoaXMua2V5LCBub25jZSwgcGxhaW50ZXh0LCBhc3NvY2lhdGVkRGF0YX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIEFFQUQgZGVjcnlwdGlvbiBvZiBgY2lwaGVydGV4dGAgd2l0aCBgYXNzb2NpYXRlZERhdGFgXG4gICAqIGFjY29yZGluZyB0byBgQ29udGV4dFIuT3BlbigpYCBhcyBkZWZpbmVkIGluXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzkxODAuaHRtbCNzZWN0aW9uLTUuMi0xMC5cbiAgICovXG4gIGFzeW5jIG9wZW4oY2lwaGVydGV4dDogVWludDhBcnJheSwgYXNzb2NpYXRlZERhdGE6IFVpbnQ4QXJyYXkpOlxuICAgICAgUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gICAgY29uc3Qgbm9uY2U6IFVpbnQ4QXJyYXkgPSB0aGlzLmNvbXB1dGVOb25jZUFuZEluY3JlbWVudFNlcXVlbmNlTnVtYmVyKCk7XG4gICAgcmV0dXJuIHRoaXMuYWVhZC5vcGVuKHtrZXk6IHRoaXMua2V5LCBub25jZSwgY2lwaGVydGV4dCwgYXNzb2NpYXRlZERhdGF9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlcyBub25jZSBhY2NvcmRpbmcgdG8gYENvbXB1dGVOb25jZWAgYXMgZGVmaW5lZCBpblxuICAgKiBAc2VlIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM5MTgwLmh0bWwjc2VjdGlvbi01LjItMTEuXG4gICAqIGZvciBzZWFsL29wZW4gYW5kIGluY3JlbWVudHMgdGhlIHNlcXVlbmNlIG51bWJlci5cbiAgICovXG4gIHByaXZhdGUgY29tcHV0ZU5vbmNlQW5kSW5jcmVtZW50U2VxdWVuY2VOdW1iZXIoKTogVWludDhBcnJheSB7XG4gICAgY29uc3Qgc2VxQnl0ZXM6IFVpbnQ4QXJyYXkgPSBocGtlVXRpbC5iaWdJbnRUb0J5dGVBcnJheShcbiAgICAgICAgdGhpcy5hZWFkLmdldE5vbmNlTGVuZ3RoKCksIHRoaXMuc2VxdWVuY2VOdW1iZXIpO1xuICAgIGNvbnN0IG5vbmNlOiBVaW50OEFycmF5ID0gYnl0ZXMueG9yKHRoaXMuYmFzZU5vbmNlLCBzZXFCeXRlcyk7XG5cbiAgICBpZiAodGhpcy5zZXF1ZW5jZU51bWJlciA+PSB0aGlzLm1heFNlcXVlbmNlTnVtYmVyKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ21lc3NhZ2UgbGltaXQgcmVhY2hlZCcpO1xuICAgIH1cbiAgICB0aGlzLnNlcXVlbmNlTnVtYmVyICs9IChCaWdJbnQoMSkpO1xuXG4gICAgcmV0dXJuIG5vbmNlO1xuICB9XG5cbiAgZ2V0S2V5KCk6IFVpbnQ4QXJyYXkge1xuICAgIHJldHVybiB0aGlzLmtleTtcbiAgfVxuXG4gIGdldEJhc2VOb25jZSgpOiBVaW50OEFycmF5IHtcbiAgICByZXR1cm4gdGhpcy5iYXNlTm9uY2U7XG4gIH1cblxuICBnZXRFbmNhcHN1bGF0ZWRLZXkoKTogVWludDhBcnJheSB7XG4gICAgcmV0dXJuIHRoaXMuZW5jYXBzdWxhdGVkS2V5O1xuICB9XG59XG5cbi8qKiBIZWxwZXIgZnVuY3Rpb24gZmFjdG9yZWQgb3V0IHRvIGZhY2lsaXRhdGUgdW5pdCB0ZXN0aW5nLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUNvbnRleHQoXG4gICAgZW5jYXBzdWxhdGVkS2V5OiBVaW50OEFycmF5LCBzaGFyZWRTZWNyZXQ6IFVpbnQ4QXJyYXksIGtlbTogSHBrZUtlbSxcbiAgICBrZGY6IEhwa2VLZGYsIGFlYWQ6IEhwa2VBZWFkLCBpbmZvOiBVaW50OEFycmF5KTogUHJvbWlzZTxIcGtlQ29udGV4dD4ge1xuICBjb25zdCBzdWl0ZUlkID0gaHBrZVV0aWwuaHBrZVN1aXRlSWQoXG4gICAgICB7a2VtSWQ6IGtlbS5nZXRLZW1JZCgpLCBrZGZJZDoga2RmLmdldEtkZklkKCksIGFlYWRJZDogYWVhZC5nZXRBZWFkSWQoKX0pO1xuXG4gIC8qKlxuICAgKiBUaGUgSUtNIHZhbHVlcyBiZWxvdyBhcmUgZW1wdHkgYmVjYXVzZSB3ZSBvbmx5IHN1cHBvcnQgYmFzZSBtb2RlXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzkxODAuaHRtbCNzZWN0aW9uLTUuMS45LlxuICAgKi9cbiAgY29uc3QgcHNrSWRIYXNoID0gYXdhaXQga2RmLmxhYmVsZWRFeHRyYWN0KHtcbiAgICBpa206IG5ldyBVaW50OEFycmF5KDApLCAgLy8gZW1wdHkgSUtNXG4gICAgaWttTGFiZWw6ICdwc2tfaWRfaGFzaCcsXG4gICAgc3VpdGVJZCxcbiAgfSk7XG5cbiAgY29uc3QgaW5mb0hhc2ggPSBhd2FpdCBrZGYubGFiZWxlZEV4dHJhY3Qoe1xuICAgIGlrbTogaW5mbyxcbiAgICBpa21MYWJlbDogJ2luZm9faGFzaCcsXG4gICAgc3VpdGVJZCxcbiAgfSk7XG5cbiAgY29uc3Qga2V5U2NoZWR1bGVDb250ZXh0ID1cbiAgICAgIGJ5dGVzLmNvbmNhdChocGtlVXRpbC5CQVNFX01PREUsIHBza0lkSGFzaCwgaW5mb0hhc2gpO1xuICBjb25zdCBzZWNyZXQgPSBhd2FpdCBrZGYubGFiZWxlZEV4dHJhY3Qoe1xuICAgIGlrbTogbmV3IFVpbnQ4QXJyYXkoMCksICAvLyBlbXB0eSBJS01cbiAgICBpa21MYWJlbDogJ3NlY3JldCcsXG4gICAgc3VpdGVJZCxcbiAgICBzYWx0OiBzaGFyZWRTZWNyZXRcbiAgfSk7XG5cbiAgY29uc3Qga2V5ID0gYXdhaXQga2RmLmxhYmVsZWRFeHBhbmQoe1xuICAgIHByazogc2VjcmV0LFxuICAgIGluZm86IGtleVNjaGVkdWxlQ29udGV4dCxcbiAgICBpbmZvTGFiZWw6ICdrZXknLFxuICAgIHN1aXRlSWQsXG4gICAgbGVuZ3RoOiBhZWFkLmdldEtleUxlbmd0aCgpXG4gIH0pO1xuICBjb25zdCBiYXNlTm9uY2UgPSBhd2FpdCBrZGYubGFiZWxlZEV4cGFuZCh7XG4gICAgcHJrOiBzZWNyZXQsXG4gICAgaW5mbzoga2V5U2NoZWR1bGVDb250ZXh0LFxuICAgIGluZm9MYWJlbDogJ2Jhc2Vfbm9uY2UnLFxuICAgIHN1aXRlSWQsXG4gICAgbGVuZ3RoOiBhZWFkLmdldE5vbmNlTGVuZ3RoKClcbiAgfSk7XG5cbiAgcmV0dXJuIG5ldyBIcGtlQ29udGV4dChlbmNhcHN1bGF0ZWRLZXksIGtleSwgYmFzZU5vbmNlLCBhZWFkKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIEhQS0Ugc2VuZGVyIGNvbnRleHQgYWNjb3JkaW5nIHRvIGBLZXlTY2hlZHVsZWAgYXMgZGVmaW5lZCBpblxuICogQHNlZSBodHRwczovL3d3dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjOTE4MC5odG1sI3NlY3Rpb24tNS4xLTkuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVTZW5kZXJDb250ZXh0KFxuICAgIHJlY2lwaWVudFB1YmxpY0tleTogVWludDhBcnJheSwga2VtOiBIcGtlS2VtLCBrZGY6IEhwa2VLZGYsIGFlYWQ6IEhwa2VBZWFkLFxuICAgIGluZm86IFVpbnQ4QXJyYXkpOiBQcm9taXNlPEhwa2VDb250ZXh0PiB7XG4gIGNvbnN0IGVuY2FwT3V0cHV0OiBIcGtlS2VtRW5jYXBPdXRwdXQgPVxuICAgICAgYXdhaXQga2VtLmVuY2Fwc3VsYXRlKHJlY2lwaWVudFB1YmxpY0tleSk7XG4gIGNvbnN0IGVuY2Fwc3VsYXRlZEtleTogVWludDhBcnJheSA9IGVuY2FwT3V0cHV0LmVuY2Fwc3VsYXRlZEtleTtcbiAgY29uc3Qgc2hhcmVkU2VjcmV0OiBVaW50OEFycmF5ID0gZW5jYXBPdXRwdXQuc2hhcmVkU2VjcmV0O1xuICByZXR1cm4gYXdhaXQgY3JlYXRlQ29udGV4dChcbiAgICAgIGVuY2Fwc3VsYXRlZEtleSwgc2hhcmVkU2VjcmV0LCBrZW0sIGtkZiwgYWVhZCwgaW5mbyk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBIUEtFIHJlY2lwaWVudCBjb250ZXh0IGFjY29yZGluZyB0byBgS2V5U2NoZWR1bGVgIGFzIGRlZmluZWQgaW5cbiAqIEBzZWUgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzkxODAuaHRtbCNzZWN0aW9uLTUuMS05LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlUmVjaXBpZW50Q29udGV4dChcbiAgICBlbmNhcHN1bGF0ZWRLZXk6IFVpbnQ4QXJyYXksXG4gICAgcmVjaXBpZW50UHJpdmF0ZUtleTogTmlzdEN1cnZlc0hwa2VLZW1Qcml2YXRlS2V5LCBrZW06IEhwa2VLZW0sXG4gICAga2RmOiBIcGtlS2RmLCBhZWFkOiBIcGtlQWVhZCwgaW5mbzogVWludDhBcnJheSk6IFByb21pc2U8SHBrZUNvbnRleHQ+IHtcbiAgY29uc3Qgc2hhcmVkU2VjcmV0OiBVaW50OEFycmF5ID1cbiAgICAgIGF3YWl0IGtlbS5kZWNhcHN1bGF0ZShlbmNhcHN1bGF0ZWRLZXksIHJlY2lwaWVudFByaXZhdGVLZXkpO1xuICByZXR1cm4gYXdhaXQgY3JlYXRlQ29udGV4dChcbiAgICAgIGVuY2Fwc3VsYXRlZEtleSwgc2hhcmVkU2VjcmV0LCBrZW0sIGtkZiwgYWVhZCwgaW5mbyk7XG59XG4iXX0=