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.

221 lines 27.8 kB
/** * @license * Copyright 2023 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 { PbHpkeKeyFormat, PbHpkePrivateKey, PbHpkePublicKey, PbKeyData } from '../../../internal/proto'; import * as bytes from '../../../subtle/bytes'; import * as ellipticCurves from '../../../subtle/elliptic_curves'; import { HybridDecrypt } from '../hybrid_decrypt'; import { HpkeDecrypt } from './hpke_decrypt'; import { HpkePublicKeyManager } from './hpke_public_key_manager'; import * as hpkeUtil from './hpke_util'; import * as hpkeValidators from './hpke_validators'; const VERSION = 0; /** * A container for methods that generate new HPKE key pairs. * These methods are separate from the KeyManager as their functionality is * independent of the primitive of the corresponding KeyManager. * @final */ class HpkePrivateKeyFactory { /** * Generates a new random HPKE key according to 'keyFormat'. * * @param keyFormat is either a KeyFormat * proto or a serialized KeyFormat proto * @return the new generated HPKE private key */ newKey(keyFormat) { return __awaiter(this, void 0, void 0, function* () { if (!keyFormat) { throw new SecurityException('Key format must be non-null.'); } const keyFormatProto = HpkePrivateKeyFactory.getKeyFormatProto(keyFormat); hpkeValidators.validateKeyFormat(keyFormatProto); const params = keyFormatProto.getParams(); if (!params) { throw new SecurityException('Params not set'); } const curveType = hpkeUtil.nistHpkeKemToCurve(params.getKem()); const curveName = ellipticCurves.curveToString(curveType); const keyPair = yield ellipticCurves.generateKeyPair('ECDH', curveName); const jsonPrivateKey = yield ellipticCurves.exportCryptoKey(keyPair.privateKey); const publicKeyBytes = yield hpkeUtil.getByteArrayFromPublicKey(keyPair.publicKey); const publicKeyProto = (new PbHpkePublicKey()) .setVersion(HpkePublicKeyManager.VERSION) .setParams(params) .setPublicKey(publicKeyBytes); const { d } = jsonPrivateKey; if (d === undefined) { throw new SecurityException('d must be set'); } return (new PbHpkePrivateKey()) .setVersion(VERSION) .setPublicKey(publicKeyProto) .setPrivateKey(bytes.fromBase64(d, true)); }); } /** * Generates a new random HPKE key based on the "serialized_key_format" and * returns it as a KeyData proto. */ newKeyData(serializedKeyFormat) { return __awaiter(this, void 0, void 0, function* () { const key = yield this.newKey(serializedKeyFormat); const keyData = (new PbKeyData()) .setTypeUrl(HpkePrivateKeyManager.KEY_TYPE) .setValue(key.serializeBinary()) .setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PRIVATE); return keyData; }); } /** * Returns an HPKE public key data extracted from the given serialized HPKE * private key. */ getPublicKeyData(serializedPrivateKey) { const privateKey = deserializePrivateKey(serializedPrivateKey); const publicKey = privateKey.getPublicKey(); if (!publicKey) { throw new SecurityException('Public key not set'); } const publicKeyData = (new PbKeyData()) .setValue(publicKey.serializeBinary()) .setTypeUrl(HpkePublicKeyManager.KEY_TYPE) .setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PUBLIC); return publicKeyData; } /** * The input keyFormat is either deserialized (in case that the input is * Uint8Array) or checked to be an HpkeKeyFormat-proto (otherwise). */ static getKeyFormatProto(keyFormat) { if (keyFormat instanceof Uint8Array) { return HpkePrivateKeyFactory.deserializeKeyFormat(keyFormat); } else if (keyFormat instanceof PbHpkeKeyFormat) { return keyFormat; } else { throw new SecurityException('Expected ' + HpkePrivateKeyManager.KEY_TYPE + ' key format proto.'); } } static deserializeKeyFormat(keyFormat) { let keyFormatProto; try { keyFormatProto = PbHpkeKeyFormat.deserializeBinary(keyFormat); } catch (e) { throw new SecurityException('Input cannot be parsed as ' + HpkePrivateKeyManager.KEY_TYPE + ' key format proto.'); } /** * Throws the same generic error to avoid discrepancies between different * versions. */ if (!keyFormatProto.getParams()) { throw new SecurityException('Input cannot be parsed as ' + HpkePrivateKeyManager.KEY_TYPE + ' key format proto.'); } return keyFormatProto; } } /** * Key manager that generates new {@link HpkePrivateKey} keys and produces new * instances of {@link HpkeDecrypt} primitives. * * @final */ export class HpkePrivateKeyManager { constructor() { this.keyFactory = new HpkePrivateKeyFactory(); } /** * Constructs an instance of the 'HybridDecrypt' primitive for a given HPKE * key. */ getPrimitive(primitiveType, key) { return __awaiter(this, void 0, void 0, function* () { if (primitiveType !== this.getPrimitiveType()) { throw new SecurityException('Requested primitive type which is not ' + 'supported by this key manager.'); } const keyProto = HpkePrivateKeyManager.getKeyProto(key); hpkeValidators.validatePrivateKey(keyProto, VERSION, HpkePublicKeyManager.VERSION); return HpkeDecrypt.createHpkeDecrypt(keyProto); }); } /** Returns true if this KeyManager supports 'HpkePrivateKey' key type. */ doesSupport(keyType) { return keyType === this.getKeyType(); } /** Returns the URL which identifies the keys managed by this KeyManager. */ getKeyType() { return HpkePrivateKeyManager.KEY_TYPE; } /** * Returns the type of primitive which can be generated by this KeyManager, * i.e. 'HybridDecrypt' */ getPrimitiveType() { return HpkePrivateKeyManager.SUPPORTED_PRIMITIVE; } getVersion() { return VERSION; } getKeyFactory() { return this.keyFactory; } static getKeyProto(keyMaterial) { if (keyMaterial instanceof PbKeyData) { return HpkePrivateKeyManager.getKeyProtoFromKeyData(keyMaterial); } if (keyMaterial instanceof PbHpkePrivateKey) { return keyMaterial; } throw new SecurityException('Key type is not supported. This key ' + 'manager supports ' + HpkePrivateKeyManager.KEY_TYPE + '.'); } static getKeyProtoFromKeyData(keyData) { if (keyData.getTypeUrl() !== HpkePrivateKeyManager.KEY_TYPE) { throw new SecurityException('Key type ' + keyData.getTypeUrl() + ' is not supported. This key manager supports ' + HpkePrivateKeyManager.KEY_TYPE + '.'); } return deserializePrivateKey(keyData.getValue()); } } HpkePrivateKeyManager.SUPPORTED_PRIMITIVE = HybridDecrypt; HpkePrivateKeyManager.KEY_TYPE = 'type.googleapis.com/google.crypto.tink.HpkePrivateKey'; /** Returns an HPKE private key instance for the given key serialization */ function deserializePrivateKey(serializedPrivateKey) { let key; try { key = PbHpkePrivateKey.deserializeBinary(serializedPrivateKey); } catch (e) { throw new SecurityException('Input cannot be parsed as ' + HpkePrivateKeyManager.KEY_TYPE + ' key-proto.'); } /** * Throws the same generic error to avoid discrepancies between different * versions. */ if (!key.getPublicKey() || !key.getPrivateKey()) { throw new SecurityException('Input cannot be parsed as ' + HpkePrivateKeyManager.KEY_TYPE + ' key-proto.'); } return key; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHBrZV9wcml2YXRlX2tleV9tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vaHlicmlkL2ludGVybmFsL2hwa2UvaHBrZV9wcml2YXRlX2tleV9tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7Ozs7Ozs7Ozs7QUFFSCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSx1Q0FBdUMsQ0FBQztBQUV4RSxPQUFPLEVBQUMsZUFBZSxFQUFnQixnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFZLE1BQU0seUJBQXlCLENBQUM7QUFHL0gsT0FBTyxLQUFLLEtBQUssTUFBTSx1QkFBdUIsQ0FBQztBQUMvQyxPQUFPLEtBQUssY0FBYyxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUVoRCxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFDL0QsT0FBTyxLQUFLLFFBQVEsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxLQUFLLGNBQWMsTUFBTSxtQkFBbUIsQ0FBQztBQUVwRCxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFFbEI7Ozs7O0dBS0c7QUFDSCxNQUFNLHFCQUFxQjtJQUN6Qjs7Ozs7O09BTUc7SUFDRyxNQUFNLENBQUMsU0FBK0I7O1lBQzFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ2QsTUFBTSxJQUFJLGlCQUFpQixDQUFDLDhCQUE4QixDQUFDLENBQUM7YUFDN0Q7WUFDRCxNQUFNLGNBQWMsR0FDaEIscUJBQXFCLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdkQsY0FBYyxDQUFDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sTUFBTSxHQUEyQixjQUFj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QUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUNuRCxDQUFDOztBQWxFdUIseUNBQW1CLEdBQUcsYUFBYSxDQUFDO0FBQ3JELDhCQUFRLEdBQUcsdURBQXVELENBQUM7QUFvRTVFLDJFQUEyRTtBQUMzRSxTQUFTLHFCQUFxQixDQUFDLG9CQUFnQztJQUU3RCxJQUFJLEdBQXFCLENBQUM7SUFDMUIsSUFBSTtRQUNGLEdBQUcsR0FBRyxnQkFBZ0IsQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0tBQ2hFO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDVixNQUFNLElBQUksaUJBQWlCLENBQ3ZCLDRCQUE0QixHQUFHLHFCQUFxQixDQUFDLFFBQVE7WUFDN0QsYUFBYSxDQUFDLENBQUM7S0FDcEI7SUFDRDs7O09BR0c7SUFDSCxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxFQUFFO1FBQy9DLE1BQU0sSUFBSSxpQkFBaUIsQ0FDdkIsNEJBQTRCLEdBQUcscUJBQXFCLENBQUMsUUFBUTtZQUM3RCxhQUFhLENBQUMsQ0FBQztLQUNwQjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHtTZWN1cml0eUV4Y2VwdGlvbn0gZnJvbSAnLi4vLi4vLi4vZXhjZXB0aW9uL3NlY3VyaXR5X2V4Y2VwdGlvbic7XG5pbXBvcnQgKiBhcyBrZXlNYW5hZ2VyIGZyb20gJy4uLy4uLy4uL2ludGVybmFsL2tleV9tYW5hZ2VyJztcbmltcG9ydCB7UGJIcGtlS2V5Rm9ybWF0LCBQYkhwa2VQYXJhbXMsIFBiSHBrZVByaXZhdGVLZXksIFBiSHBrZVB1YmxpY0tleSwgUGJLZXlEYXRhLCBQYk1lc3NhZ2V9IGZyb20gJy4uLy4uLy4uL2ludGVybmFsL3Byb3RvJztcbmltcG9ydCB7UHJvdG9CeXRlc30gZnJvbSAnLi4vLi4vLi4vaW50ZXJuYWwvcHJvdG9fc2hpbXMnO1xuaW1wb3J0ICogYXMgdXRpbCBmcm9tICcuLi8uLi8uLi9pbnRlcm5hbC91dGlsJztcbmltcG9ydCAqIGFzIGJ5dGVzIGZyb20gJy4uLy4uLy4uL3N1YnRsZS9ieXRlcyc7XG5pbXBvcnQgKiBhcyBlbGxpcHRpY0N1cnZlcyBmcm9tICcuLi8uLi8uLi9zdWJ0bGUvZWxsaXB0aWNfY3VydmVzJztcbmltcG9ydCB7SHlicmlkRGVjcnlwdH0gZnJvbSAnLi4vaHlicmlkX2RlY3J5cHQnO1xuXG5pbXBvcnQge0hwa2VEZWNyeXB0fSBmcm9tICcuL2hwa2VfZGVjcnlwdCc7XG5pbXBvcnQge0hwa2VQdWJsaWNLZXlNYW5hZ2VyfSBmcm9tICcuL2hwa2VfcHVibGljX2tleV9tYW5hZ2VyJztcbmltcG9ydCAqIGFzIGhwa2VVdGlsIGZyb20gJy4vaHBrZV91dGlsJztcbmltcG9ydCAqIGFzIGhwa2VWYWxpZGF0b3JzIGZyb20gJy4vaHBrZV92YWxpZGF0b3JzJztcblxuY29uc3QgVkVSU0lPTiA9IDA7XG5cbi8qKlxuICogQSBjb250YWluZXIgZm9yIG1ldGhvZHMgdGhhdCBnZW5lcmF0ZSBuZXcgSFBLRSBrZXkgcGFpcnMuXG4gKiBUaGVzZSBtZXRob2RzIGFyZSBzZXBhcmF0ZSBmcm9tIHRoZSBLZXlNYW5hZ2VyIGFzIHRoZWlyIGZ1bmN0aW9uYWxpdHkgaXNcbiAqIGluZGVwZW5kZW50IG9mIHRoZSBwcmltaXRpdmUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgS2V5TWFuYWdlci5cbiAqIEBmaW5hbFxuICovXG5jbGFzcyBIcGtlUHJpdmF0ZUtleUZhY3RvcnkgaW1wbGVtZW50cyBrZXlNYW5hZ2VyLlByaXZhdGVLZXlGYWN0b3J5IHtcbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhIG5ldyByYW5kb20gSFBLRSBrZXkgYWNjb3JkaW5nIHRvICdrZXlGb3JtYXQnLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5Rm9ybWF0IGlzIGVpdGhlciBhIEtleUZvcm1hdFxuICAgKiAgICAgcHJvdG8gb3IgYSBzZXJpYWxpemVkIEtleUZvcm1hdCBwcm90b1xuICAgKiBAcmV0dXJuIHRoZSBuZXcgZ2VuZXJhdGVkIEhQS0UgcHJpdmF0ZSBrZXlcbiAgICovXG4gIGFzeW5jIG5ld0tleShrZXlGb3JtYXQ6IFBiTWVzc2FnZXxVaW50OEFycmF5KTogUHJvbWlzZTxQYkhwa2VQcml2YXRlS2V5PiB7XG4gICAgaWYgKCFrZXlGb3JtYXQpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignS2V5IGZvcm1hdCBtdXN0IGJlIG5vbi1udWxsLicpO1xuICAgIH1cbiAgICBjb25zdCBrZXlGb3JtYXRQcm90bzogUGJIcGtlS2V5Rm9ybWF0ID1cbiAgICAgICAgSHBrZVByaXZhdGVLZXlGYWN0b3J5LmdldEtleUZvcm1hdFByb3RvKGtleUZvcm1hdCk7XG4gICAgaHBrZVZhbGlkYXRvcnMudmFsaWRhdGVLZXlGb3JtYXQoa2V5Rm9ybWF0UHJvdG8pO1xuICAgIGNvbnN0IHBhcmFtczogUGJIcGtlUGFyYW1zfHVuZGVmaW5lZCA9IGtleUZvcm1hdFByb3RvLmdldFBhcmFtcygpO1xuICAgIGlmICghcGFyYW1zKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1BhcmFtcyBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGN1cnZlVHlwZTogZWxsaXB0aWNDdXJ2ZXMuQ3VydmVUeXBlLlAyNTZ8XG4gICAgICAgIGVsbGlwdGljQ3VydmVzLkN1cnZlVHlwZS5QNTIxID1cbiAgICAgICAgaHBrZVV0aWwubmlzdEhwa2VLZW1Ub0N1cnZlKHBhcmFtcy5nZXRLZW0oKSk7XG4gICAgY29uc3QgY3VydmVOYW1lID0gZWxsaXB0aWNDdXJ2ZXMuY3VydmVUb1N0cmluZyhjdXJ2ZVR5cGUpO1xuICAgIGNvbnN0IGtleVBhaXI6IENyeXB0b0tleVBhaXIgPVxuICAgICAgICBhd2FpdCBlbGxpcHRpY0N1cnZlcy5nZW5lcmF0ZUtleVBhaXIoJ0VDREgnLCBjdXJ2ZU5hbWUpO1xuICAgIGNvbnN0IGpzb25Qcml2YXRlS2V5ID1cbiAgICAgICAgYXdhaXQgZWxsaXB0aWNDdXJ2ZXMuZXhwb3J0Q3J5cHRvS2V5KGtleVBhaXIucHJpdmF0ZUtleSk7XG5cbiAgICBjb25zdCBwdWJsaWNLZXlCeXRlcyA9XG4gICAgICAgIGF3YWl0IGhwa2VVdGlsLmdldEJ5dGVBcnJheUZyb21QdWJsaWNLZXkoa2V5UGFpci5wdWJsaWNLZXkpO1xuXG4gICAgY29uc3QgcHVibGljS2V5UHJvdG8gPSAobmV3IFBiSHBrZVB1YmxpY0tleSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRWZXJzaW9uKEhwa2VQdWJsaWNLZXlNYW5hZ2VyLlZFUlNJT04pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFBhcmFtcyhwYXJhbXMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFB1YmxpY0tleShwdWJsaWNLZXlCeXRlcyk7XG5cbiAgICBjb25zdCB7ZH0gPSBqc29uUHJpdmF0ZUtleTtcbiAgICBpZiAoZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ2QgbXVzdCBiZSBzZXQnKTtcbiAgICB9XG4gICAgcmV0dXJuIChuZXcgUGJIcGtlUHJpdmF0ZUtleSgpKVxuICAgICAgICAuc2V0VmVyc2lvbihWRVJTSU9OKVxuICAgICAgICAuc2V0UHVibGljS2V5KHB1YmxpY0tleVByb3RvKVxuICAgICAgICAuc2V0UHJpdmF0ZUtleShieXRlcy5mcm9tQmFzZTY0KGQsIHRydWUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSBuZXcgcmFuZG9tIEhQS0Uga2V5IGJhc2VkIG9uIHRoZSBcInNlcmlhbGl6ZWRfa2V5X2Zvcm1hdFwiIGFuZFxuICAgKiByZXR1cm5zIGl0IGFzIGEgS2V5RGF0YSBwcm90by5cbiAgICovXG4gIGFzeW5jIG5ld0tleURhdGEoc2VyaWFsaXplZEtleUZvcm1hdDogUGJNZXNzYWdlfFxuICAgICAgICAgICAgICAgICAgIFVpbnQ4QXJyYXkpOiBQcm9taXNlPFBiS2V5RGF0YT4ge1xuICAgIGNvbnN0IGtleTogUGJIcGtlUHJpdmF0ZUtleSA9IGF3YWl0IHRoaXMubmV3S2V5KHNlcmlhbGl6ZWRLZXlGb3JtYXQpO1xuICAgIGNvbnN0IGtleURhdGEgPVxuICAgICAgICAobmV3IFBiS2V5RGF0YSgpKVxuICAgICAgICAgICAgLnNldFR5cGVVcmwoSHBrZVByaXZhdGVLZXlNYW5hZ2VyLktFWV9UWVBFKVxuICAgICAgICAgICAgLnNldFZhbHVlKGtleS5zZXJpYWxpemVCaW5hcnkoKSlcbiAgICAgICAgICAgIC5zZXRLZXlNYXRlcmlhbFR5cGUoUGJLZXlEYXRhLktleU1hdGVyaWFsVHlwZS5BU1lNTUVUUklDX1BSSVZBVEUpO1xuICAgIHJldHVybiBrZXlEYXRhO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gSFBLRSBwdWJsaWMga2V5IGRhdGEgZXh0cmFjdGVkIGZyb20gdGhlIGdpdmVuIHNlcmlhbGl6ZWQgSFBLRVxuICAgKiBwcml2YXRlIGtleS5cbiAgICovXG4gIGdldFB1YmxpY0tleURhdGEoc2VyaWFsaXplZFByaXZhdGVLZXk6IFVpbnQ4QXJyYXkpOiBQYktleURhdGEge1xuICAgIGNvbnN0IHByaXZhdGVLZXk6IFBiSHBrZVByaXZhdGVLZXkgPVxuICAgICAgICBkZXNlcmlhbGl6ZVByaXZhdGVLZXkoc2VyaWFsaXplZFByaXZhdGVLZXkpO1xuICAgIGNvbnN0IHB1YmxpY0tleTogUGJIcGtlUHVibGljS2V5fHVuZGVmaW5lZCA9IHByaXZhdGVLZXkuZ2V0UHVibGljS2V5KCk7XG4gICAgaWYgKCFwdWJsaWNLZXkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignUHVibGljIGtleSBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IHB1YmxpY0tleURhdGEgPVxuICAgICAgICAobmV3IFBiS2V5RGF0YSgpKVxuICAgICAgICAgICAgLnNldFZhbHVlKHB1YmxpY0tleS5zZXJpYWxpemVCaW5hcnkoKSlcbiAgICAgICAgICAgIC5zZXRUeXBlVXJsKEhwa2VQdWJsaWNLZXlNYW5hZ2VyLktFWV9UWVBFKVxuICAgICAgICAgICAgLnNldEtleU1hdGVyaWFsVHlwZShQYktleURhdGEuS2V5TWF0ZXJpYWxUeXBlLkFTWU1NRVRSSUNfUFVCTElDKTtcbiAgICByZXR1cm4gcHVibGljS2V5RGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW5wdXQga2V5Rm9ybWF0IGlzIGVpdGhlciBkZXNlcmlhbGl6ZWQgKGluIGNhc2UgdGhhdCB0aGUgaW5wdXQgaXNcbiAgICogVWludDhBcnJheSkgb3IgY2hlY2tlZCB0byBiZSBhbiBIcGtlS2V5Rm9ybWF0LXByb3RvIChvdGhlcndpc2UpLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0S2V5Rm9ybWF0UHJvdG8oa2V5Rm9ybWF0OiBQYk1lc3NhZ2V8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVpbnQ4QXJyYXkpOiBQYkhwa2VLZXlGb3JtYXQge1xuICAgIGlmIChrZXlGb3JtYXQgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICByZXR1cm4gSHBrZVByaXZhdGVLZXlGYWN0b3J5LmRlc2VyaWFsaXplS2V5Rm9ybWF0KGtleUZvcm1hdCk7XG4gICAgfSBlbHNlIGlmIChrZXlGb3JtYXQgaW5zdGFuY2VvZiBQYkhwa2VLZXlGb3JtYXQpIHtcbiAgICAgIHJldHVybiBrZXlGb3JtYXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnRXhwZWN0ZWQgJyArIEhwa2VQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArICcga2V5IGZvcm1hdCBwcm90by4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBkZXNlcmlhbGl6ZUtleUZvcm1hdChrZXlGb3JtYXQ6IFVpbnQ4QXJyYXkpOiBQYkhwa2VLZXlGb3JtYXQge1xuICAgIGxldCBrZXlGb3JtYXRQcm90bzogUGJIcGtlS2V5Rm9ybWF0O1xuICAgIHRyeSB7XG4gICAgICBrZXlGb3JtYXRQcm90byA9IFBiSHBrZUtleUZvcm1hdC5kZXNlcmlhbGl6ZUJpbmFyeShrZXlGb3JtYXQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW5wdXQgY2Fubm90IGJlIHBhcnNlZCBhcyAnICsgSHBrZVByaXZhdGVLZXlNYW5hZ2VyLktFWV9UWVBFICtcbiAgICAgICAgICAnIGtleSBmb3JtYXQgcHJvdG8uJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRocm93cyB0aGUgc2FtZSBnZW5lcmljIGVycm9yIHRvIGF2b2lkIGRpc2NyZXBhbmNpZXMgYmV0d2VlbiBkaWZmZXJlbnRcbiAgICAgKiB2ZXJzaW9ucy5cbiAgICAgKi9cbiAgICBpZiAoIWtleUZvcm1hdFByb3RvLmdldFBhcmFtcygpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEhwa2VQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArXG4gICAgICAgICAgJyBrZXkgZm9ybWF0IHByb3RvLicpO1xuICAgIH1cbiAgICByZXR1cm4ga2V5Rm9ybWF0UHJvdG87XG4gIH1cbn1cblxuLyoqXG4gKiBLZXkgbWFuYWdlciB0aGF0IGdlbmVyYXRlcyBuZXcge0BsaW5rIEhwa2VQcml2YXRlS2V5fSBrZXlzIGFuZCBwcm9kdWNlcyBuZXdcbiAqIGluc3RhbmNlcyBvZiB7QGxpbmsgSHBrZURlY3J5cHR9IHByaW1pdGl2ZXMuXG4gKlxuICogQGZpbmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBIcGtlUHJpdmF0ZUtleU1hbmFnZXIgaW1wbGVtZW50c1xuICAgIGtleU1hbmFnZXIuS2V5TWFuYWdlcjxIeWJyaWREZWNyeXB0PiB7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFNVUFBPUlRFRF9QUklNSVRJVkUgPSBIeWJyaWREZWNyeXB0O1xuICBzdGF0aWMgS0VZX1RZUEUgPSAndHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuSHBrZVByaXZhdGVLZXknO1xuICBrZXlGYWN0b3J5ID0gbmV3IEhwa2VQcml2YXRlS2V5RmFjdG9yeSgpO1xuICAvKipcbiAgICogQ29uc3RydWN0cyBhbiBpbnN0YW5jZSBvZiB0aGUgJ0h5YnJpZERlY3J5cHQnIHByaW1pdGl2ZSBmb3IgYSBnaXZlbiBIUEtFXG4gICAqIGtleS5cbiAgICovXG4gIGFzeW5jIGdldFByaW1pdGl2ZShcbiAgICAgIHByaW1pdGl2ZVR5cGU6IHV0aWwuQ29uc3RydWN0b3I8SHlicmlkRGVjcnlwdD4sXG4gICAgICBrZXk6IFBiS2V5RGF0YXxQYk1lc3NhZ2UpOiBQcm9taXNlPEh5YnJpZERlY3J5cHQ+IHtcbiAgICBpZiAocHJpbWl0aXZlVHlwZSAhPT0gdGhpcy5nZXRQcmltaXRpdmVUeXBlKCkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnUmVxdWVzdGVkIHByaW1pdGl2ZSB0eXBlIHdoaWNoIGlzIG5vdCAnICtcbiAgICAgICAgICAnc3VwcG9ydGVkIGJ5IHRoaXMga2V5IG1hbmFnZXIuJyk7XG4gICAgfVxuICAgIGNvbnN0IGtleVByb3RvOiBQYkhwa2VQcml2YXRlS2V5ID0gSHBrZVByaXZhdGVLZXlNYW5hZ2VyLmdldEtleVByb3RvKGtleSk7XG4gICAgaHBrZVZhbGlkYXRvcnMudmFsaWRhdGVQcml2YXRlS2V5KFxuICAgICAgICBrZXlQcm90bywgVkVSU0lPTiwgSHBrZVB1YmxpY0tleU1hbmFnZXIuVkVSU0lPTik7XG4gICAgcmV0dXJuIEhwa2VEZWNyeXB0LmNyZWF0ZUhwa2VEZWNyeXB0KGtleVByb3RvKTtcbiAgfVxuXG4gIC8qKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBLZXlNYW5hZ2VyIHN1cHBvcnRzICdIcGtlUHJpdmF0ZUtleScga2V5IHR5cGUuICovXG4gIGRvZXNTdXBwb3J0KGtleVR5cGU6IHN0cmluZykge1xuICAgIHJldHVybiBrZXlUeXBlID09PSB0aGlzLmdldEtleVR5cGUoKTtcbiAgfVxuICAvKiogUmV0dXJucyB0aGUgVVJMIHdoaWNoIGlkZW50aWZpZXMgdGhlIGtleXMgbWFuYWdlZCBieSB0aGlzIEtleU1hbmFnZXIuICovXG4gIGdldEtleVR5cGUoKSB7XG4gICAgcmV0dXJuIEhwa2VQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRTtcbiAgfVxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdHlwZSBvZiBwcmltaXRpdmUgd2hpY2ggY2FuIGJlIGdlbmVyYXRlZCBieSB0aGlzIEtleU1hbmFnZXIsXG4gICAqIGkuZS4gJ0h5YnJpZERlY3J5cHQnXG4gICAqL1xuICBnZXRQcmltaXRpdmVUeXBlKCkge1xuICAgIHJldHVybiBIcGtlUHJpdmF0ZUtleU1hbmFnZXIuU1VQUE9SVEVEX1BSSU1JVElWRTtcbiAgfVxuXG4gIGdldFZlcnNpb24oKSB7XG4gICAgcmV0dXJuIFZFUlNJT047XG4gIH1cblxuICBnZXRLZXlGYWN0b3J5KCkge1xuICAgIHJldHVybiB0aGlzLmtleUZhY3Rvcnk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRLZXlQcm90byhrZXlNYXRlcmlhbDogUGJLZXlEYXRhfFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYk1lc3NhZ2UpOiBQYkhwa2VQcml2YXRlS2V5IHtcbiAgICBpZiAoa2V5TWF0ZXJpYWwgaW5zdGFuY2VvZiBQYktleURhdGEpIHtcbiAgICAgIHJldHVybiBIcGtlUHJpdmF0ZUtleU1hbmFnZXIuZ2V0S2V5UHJvdG9Gcm9tS2V5RGF0YShrZXlNYXRlcmlhbCk7XG4gICAgfVxuICAgIGlmIChrZXlNYXRlcmlhbCBpbnN0YW5jZW9mIFBiSHBrZVByaXZhdGVLZXkpIHtcbiAgICAgIHJldHVybiBrZXlNYXRlcmlhbDtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAnS2V5IHR5cGUgaXMgbm90IHN1cHBvcnRlZC4gVGhpcyBrZXkgJyArXG4gICAgICAgICdtYW5hZ2VyIHN1cHBvcnRzICcgKyBIcGtlUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUgKyAnLicpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0S2V5UHJvdG9Gcm9tS2V5RGF0YShrZXlEYXRhOiBQYktleURhdGEpOiBQYkhwa2VQcml2YXRlS2V5IHtcbiAgICBpZiAoa2V5RGF0YS5nZXRUeXBlVXJsKCkgIT09IEhwa2VQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdLZXkgdHlwZSAnICsga2V5RGF0YS5nZXRUeXBlVXJsKCkgK1xuICAgICAgICAgICcgaXMgbm90IHN1cHBvcnRlZC4gVGhpcyBrZXkgbWFuYWdlciBzdXBwb3J0cyAnICtcbiAgICAgICAgICBIcGtlUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUgKyAnLicpO1xuICAgIH1cbiAgICByZXR1cm4gZGVzZXJpYWxpemVQcml2YXRlS2V5KGtleURhdGEuZ2V0VmFsdWUoKSk7XG4gIH1cbn1cblxuLyoqIFJldHVybnMgYW4gSFBLRSBwcml2YXRlIGtleSBpbnN0YW5jZSBmb3IgdGhlIGdpdmVuIGtleSBzZXJpYWxpemF0aW9uICovXG5mdW5jdGlvbiBkZXNlcmlhbGl6ZVByaXZhdGVLZXkoc2VyaWFsaXplZFByaXZhdGVLZXk6IFByb3RvQnl0ZXMpOlxuICAgIFBiSHBrZVByaXZhdGVLZXkge1xuICBsZXQga2V5OiBQYkhwa2VQcml2YXRlS2V5O1xuICB0cnkge1xuICAgIGtleSA9IFBiSHBrZVByaXZhdGVLZXkuZGVzZXJpYWxpemVCaW5hcnkoc2VyaWFsaXplZFByaXZhdGVLZXkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAnSW5wdXQgY2Fubm90IGJlIHBhcnNlZCBhcyAnICsgSHBrZVByaXZhdGVLZXlNYW5hZ2VyLktFWV9UWVBFICtcbiAgICAgICAgJyBrZXktcHJvdG8uJyk7XG4gIH1cbiAgLyoqXG4gICAqIFRocm93cyB0aGUgc2FtZSBnZW5lcmljIGVycm9yIHRvIGF2b2lkIGRpc2NyZXBhbmNpZXMgYmV0d2VlbiBkaWZmZXJlbnRcbiAgICogdmVyc2lvbnMuXG4gICAqL1xuICBpZiAoIWtleS5nZXRQdWJsaWNLZXkoKSB8fCAha2V5LmdldFByaXZhdGVLZXkoKSkge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEhwa2VQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArXG4gICAgICAgICcga2V5LXByb3RvLicpO1xuICB9XG4gIHJldHVybiBrZXk7XG59XG4iXX0=