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.

237 lines 32.5 kB
/** * @license * Copyright 2020 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 { PbEciesAeadHkdfKeyFormat, PbEciesAeadHkdfPrivateKey, PbEciesAeadHkdfPublicKey, PbKeyData } from '../internal/proto'; import { bytesAsU8 } from '../internal/proto_shims'; import * as Util from '../internal/util'; import * as Bytes from '../subtle/bytes'; import * as eciesAeadHkdfHybridDecrypt from '../subtle/ecies_aead_hkdf_hybrid_decrypt'; import * as EllipticCurves from '../subtle/elliptic_curves'; import { EciesAeadHkdfPublicKeyManager } from './ecies_aead_hkdf_public_key_manager'; import * as EciesAeadHkdfUtil from './ecies_aead_hkdf_util'; import * as EciesAeadHkdfValidators from './ecies_aead_hkdf_validators'; import { HybridDecrypt } from './internal/hybrid_decrypt'; import { RegistryEciesAeadHkdfDemHelper } from './registry_ecies_aead_hkdf_dem_helper'; const VERSION = 0; /** * @final */ class EciesAeadHkdfPrivateKeyFactory { /** */ newKey(keyFormat) { return __awaiter(this, void 0, void 0, function* () { if (!keyFormat) { throw new SecurityException('Key format has to be non-null.'); } const keyFormatProto = EciesAeadHkdfPrivateKeyFactory.getKeyFormatProto(keyFormat); EciesAeadHkdfValidators.validateKeyFormat(keyFormatProto); const params = keyFormatProto.getParams(); if (!params) { throw new SecurityException('Params not set'); } const kemParams = params.getKemParams(); if (!kemParams) { throw new SecurityException('KEM params not set'); } const curveTypeProto = kemParams.getCurveType(); const curveTypeSubtle = Util.curveTypeProtoToSubtle(curveTypeProto); const curveName = EllipticCurves.curveToString(curveTypeSubtle); const keyPair = yield EllipticCurves.generateKeyPair('ECDH', curveName); const jsonPublicKey = yield EllipticCurves.exportCryptoKey(keyPair.publicKey); const jsonPrivateKey = yield EllipticCurves.exportCryptoKey(keyPair.privateKey); return EciesAeadHkdfPrivateKeyFactory.jsonToProtoKey(jsonPrivateKey, jsonPublicKey, params); }); } /** */ newKeyData(serializedKeyFormat) { return __awaiter(this, void 0, void 0, function* () { const key = yield this.newKey(serializedKeyFormat); const keyData = (new PbKeyData()) .setTypeUrl(EciesAeadHkdfPrivateKeyManager.KEY_TYPE) .setValue(key.serializeBinary()) .setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PRIVATE); return keyData; }); } 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(EciesAeadHkdfPublicKeyManager.KEY_TYPE) .setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PUBLIC); return publicKeyData; } /** * Creates a private key proto corresponding to given JSON key pair and with * the given params. * */ static jsonToProtoKey(jsonPrivateKey, jsonPublicKey, params) { const { x, y } = jsonPublicKey; if (x === undefined) { throw new SecurityException('x must be set'); } if (y === undefined) { throw new SecurityException('y must be set'); } const publicKeyProto = (new PbEciesAeadHkdfPublicKey()) .setVersion(EciesAeadHkdfPublicKeyManager.VERSION) .setParams(params) .setX(Bytes.fromBase64(x, true)) .setY(Bytes.fromBase64(y, true)); const { d } = jsonPrivateKey; if (d === undefined) { throw new SecurityException('d must be set'); } const privateKeyProto = (new PbEciesAeadHkdfPrivateKey()) .setVersion(VERSION) .setPublicKey(publicKeyProto) .setKeyValue(Bytes.fromBase64(d, true)); return privateKeyProto; } /** * The input keyFormat is either deserialized (in case that the input is * Uint8Array) or checked to be an EciesAeadHkdfKeyFormat-proto (otherwise). * */ static getKeyFormatProto(keyFormat) { if (keyFormat instanceof Uint8Array) { return EciesAeadHkdfPrivateKeyFactory.deserializeKeyFormat(keyFormat); } else if (keyFormat instanceof PbEciesAeadHkdfKeyFormat) { return keyFormat; } else { throw new SecurityException('Expected ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key format proto.'); } } static deserializeKeyFormat(keyFormat) { let keyFormatProto; try { keyFormatProto = PbEciesAeadHkdfKeyFormat.deserializeBinary(keyFormat); } catch (e) { throw new SecurityException('Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key format proto.'); } if (!keyFormatProto.getParams()) { throw new SecurityException('Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key format proto.'); } return keyFormatProto; } } /** * @final */ export class EciesAeadHkdfPrivateKeyManager { constructor() { this.keyFactory = new EciesAeadHkdfPrivateKeyFactory(); } 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 = EciesAeadHkdfPrivateKeyManager.getKeyProto(key); EciesAeadHkdfValidators.validatePrivateKey(keyProto, VERSION, EciesAeadHkdfPublicKeyManager.VERSION); const recepientPrivateKey = EciesAeadHkdfUtil.getJsonWebKeyFromProto(keyProto); const publicKey = keyProto.getPublicKey(); if (!publicKey) { throw new SecurityException('Public key not set'); } const params = publicKey.getParams(); if (!params) { throw new SecurityException('Params not set'); } const demParams = params.getDemParams(); if (!demParams) { throw new SecurityException('DEM params not set'); } const keyTemplate = (demParams.getAeadDem()); if (!keyTemplate) { throw new SecurityException('Key template not set'); } const demHelper = new RegistryEciesAeadHkdfDemHelper(keyTemplate); const pointFormat = Util.pointFormatProtoToSubtle(params.getEcPointFormat()); const kemParams = params.getKemParams(); if (!kemParams) { throw new SecurityException('KEM params not set'); } const hkdfHash = Util.hashTypeProtoToString(kemParams.getHkdfHashType()); const hkdfSalt = bytesAsU8(kemParams.getHkdfSalt()); return eciesAeadHkdfHybridDecrypt.fromJsonWebKey(recepientPrivateKey, hkdfHash, pointFormat, demHelper, hkdfSalt); }); } doesSupport(keyType) { return keyType === this.getKeyType(); } getKeyType() { return EciesAeadHkdfPrivateKeyManager.KEY_TYPE; } getPrimitiveType() { return EciesAeadHkdfPrivateKeyManager.SUPPORTED_PRIMITIVE; } getVersion() { return VERSION; } getKeyFactory() { return this.keyFactory; } static getKeyProto(keyMaterial) { if (keyMaterial instanceof PbKeyData) { return EciesAeadHkdfPrivateKeyManager.getKeyProtoFromKeyData(keyMaterial); } if (keyMaterial instanceof PbEciesAeadHkdfPrivateKey) { return keyMaterial; } throw new SecurityException('Key type is not supported. This key ' + 'manager supports ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + '.'); } static getKeyProtoFromKeyData(keyData) { if (keyData.getTypeUrl() !== EciesAeadHkdfPrivateKeyManager.KEY_TYPE) { throw new SecurityException('Key type ' + keyData.getTypeUrl() + ' is not supported. This key manager supports ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + '.'); } return deserializePrivateKey(keyData.getValue()); } } EciesAeadHkdfPrivateKeyManager.SUPPORTED_PRIMITIVE = HybridDecrypt; EciesAeadHkdfPrivateKeyManager.KEY_TYPE = 'type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey'; function deserializePrivateKey(serializedPrivateKey) { let key; try { key = PbEciesAeadHkdfPrivateKey.deserializeBinary(serializedPrivateKey); } catch (e) { throw new SecurityException('Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key-proto.'); } if (!key.getPublicKey() || !key.getKeyValue()) { throw new SecurityException('Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key-proto.'); } return key; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNpZXNfYWVhZF9oa2RmX3ByaXZhdGVfa2V5X21hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9oeWJyaWQvZWNpZXNfYWVhZF9oa2RmX3ByaXZhdGVfa2V5X21hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRzs7Ozs7Ozs7OztBQUVILE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGlDQUFpQyxDQUFDO0FBRWxFLE9BQU8sRUFBQyx3QkFBd0IsRUFBeUIseUJBQXlCLEVBQUUsd0JBQXdCLEVBQUUsU0FBUyxFQUFZLE1BQU0sbUJBQW1CLENBQUM7QUFDN0osT0FBTyxFQUFDLFNBQVMsRUFBYSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxLQUFLLEtBQUssTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEtBQUssMEJBQTBCLE1BQU0sMENBQTBDLENBQUM7QUFDdkYsT0FBTyxLQUFLLGNBQWMsTUFBTSwyQkFBMkIsQ0FBQztBQUU1RCxPQUFPLEVBQUMsNkJBQTZCLEVBQUMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNuRixPQUFPLEtBQUssaUJBQWlCLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQsT0FBTyxLQUFLLHVCQUF1QixNQUFNLDhCQUE4QixDQUFDO0FBQ3hFLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsOEJBQThCLEVBQUMsTUFBTSx1Q0FBdUMsQ0FBQztBQUVyRixNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFFbEI7O0dBRUc7QUFDSCxNQUFNLDhCQUE4QjtJQUNsQztPQUNHO0lBQ0csTUFBTSxDQUFDLFNBQ1U7O1lBQ3JCLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ2QsTUFBTSxJQUFJLGlCQUFpQixDQUFDLGdDQUFnQyxDQUFDLENBQUM7YUFDL0Q7WUFD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N0QsSUFBSSxHQUE4QixDQUFDO0lBQ25DLElBQUk7UUFDRixHQUFHLEdBQUcseUJBQXlCLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLENBQUMsQ0FBQztLQUN6RTtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsTUFBTSxJQUFJLGlCQUFpQixDQUN2Qiw0QkFBNEIsR0FBRyw4QkFBOEIsQ0FBQyxRQUFRO1lBQ3RFLGFBQWEsQ0FBQyxDQUFDO0tBQ3BCO0lBQ0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsRUFBRTtRQUM3QyxNQUFNLElBQUksaUJBQWlCLENBQ3ZCLDRCQUE0QixHQUFHLDhCQUE4QixDQUFDLFFBQVE7WUFDdEUsYUFBYSxDQUFDLENBQUM7S0FDcEI7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCB7U2VjdXJpdHlFeGNlcHRpb259IGZyb20gJy4uL2V4Y2VwdGlvbi9zZWN1cml0eV9leGNlcHRpb24nO1xuaW1wb3J0ICogYXMgS2V5TWFuYWdlciBmcm9tICcuLi9pbnRlcm5hbC9rZXlfbWFuYWdlcic7XG5pbXBvcnQge1BiRWNpZXNBZWFkSGtkZktleUZvcm1hdCwgUGJFY2llc0FlYWRIa2RmUGFyYW1zLCBQYkVjaWVzQWVhZEhrZGZQcml2YXRlS2V5LCBQYkVjaWVzQWVhZEhrZGZQdWJsaWNLZXksIFBiS2V5RGF0YSwgUGJNZXNzYWdlfSBmcm9tICcuLi9pbnRlcm5hbC9wcm90byc7XG5pbXBvcnQge2J5dGVzQXNVOCwgUHJvdG9CeXRlc30gZnJvbSAnLi4vaW50ZXJuYWwvcHJvdG9fc2hpbXMnO1xuaW1wb3J0ICogYXMgVXRpbCBmcm9tICcuLi9pbnRlcm5hbC91dGlsJztcbmltcG9ydCAqIGFzIEJ5dGVzIGZyb20gJy4uL3N1YnRsZS9ieXRlcyc7XG5pbXBvcnQgKiBhcyBlY2llc0FlYWRIa2RmSHlicmlkRGVjcnlwdCBmcm9tICcuLi9zdWJ0bGUvZWNpZXNfYWVhZF9oa2RmX2h5YnJpZF9kZWNyeXB0JztcbmltcG9ydCAqIGFzIEVsbGlwdGljQ3VydmVzIGZyb20gJy4uL3N1YnRsZS9lbGxpcHRpY19jdXJ2ZXMnO1xuXG5pbXBvcnQge0VjaWVzQWVhZEhrZGZQdWJsaWNLZXlNYW5hZ2VyfSBmcm9tICcuL2VjaWVzX2FlYWRfaGtkZl9wdWJsaWNfa2V5X21hbmFnZXInO1xuaW1wb3J0ICogYXMgRWNpZXNBZWFkSGtkZlV0aWwgZnJvbSAnLi9lY2llc19hZWFkX2hrZGZfdXRpbCc7XG5pbXBvcnQgKiBhcyBFY2llc0FlYWRIa2RmVmFsaWRhdG9ycyBmcm9tICcuL2VjaWVzX2FlYWRfaGtkZl92YWxpZGF0b3JzJztcbmltcG9ydCB7SHlicmlkRGVjcnlwdH0gZnJvbSAnLi9pbnRlcm5hbC9oeWJyaWRfZGVjcnlwdCc7XG5pbXBvcnQge1JlZ2lzdHJ5RWNpZXNBZWFkSGtkZkRlbUhlbHBlcn0gZnJvbSAnLi9yZWdpc3RyeV9lY2llc19hZWFkX2hrZGZfZGVtX2hlbHBlcic7XG5cbmNvbnN0IFZFUlNJT04gPSAwO1xuXG4vKipcbiAqIEBmaW5hbFxuICovXG5jbGFzcyBFY2llc0FlYWRIa2RmUHJpdmF0ZUtleUZhY3RvcnkgaW1wbGVtZW50cyBLZXlNYW5hZ2VyLlByaXZhdGVLZXlGYWN0b3J5IHtcbiAgLyoqXG4gICAqL1xuICBhc3luYyBuZXdLZXkoa2V5Rm9ybWF0OiBQYk1lc3NhZ2V8XG4gICAgICAgICAgICAgICBVaW50OEFycmF5KTogUHJvbWlzZTxQYkVjaWVzQWVhZEhrZGZQcml2YXRlS2V5PiB7XG4gICAgaWYgKCFrZXlGb3JtYXQpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignS2V5IGZvcm1hdCBoYXMgdG8gYmUgbm9uLW51bGwuJyk7XG4gICAgfVxuICAgIGNvbnN0IGtleUZvcm1hdFByb3RvID1cbiAgICAgICAgRWNpZXNBZWFkSGtkZlByaXZhdGVLZXlGYWN0b3J5LmdldEtleUZvcm1hdFByb3RvKGtleUZvcm1hdCk7XG4gICAgRWNpZXNBZWFkSGtkZlZhbGlkYXRvcnMudmFsaWRhdGVLZXlGb3JtYXQoa2V5Rm9ybWF0UHJvdG8pO1xuICAgIGNvbnN0IHBhcmFtcyA9IGtleUZvcm1hdFByb3RvLmdldFBhcmFtcygpO1xuICAgIGlmICghcGFyYW1zKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1BhcmFtcyBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGtlbVBhcmFtcyA9IHBhcmFtcy5nZXRLZW1QYXJhbXMoKTtcbiAgICBpZiAoIWtlbVBhcmFtcykge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKCdLRU0gcGFyYW1zIG5vdCBzZXQnKTtcbiAgICB9XG4gICAgY29uc3QgY3VydmVUeXBlUHJvdG8gPSBrZW1QYXJhbXMuZ2V0Q3VydmVUeXBlKCk7XG4gICAgY29uc3QgY3VydmVUeXBlU3VidGxlID0gVXRpbC5jdXJ2ZVR5cGVQcm90b1RvU3VidGxlKGN1cnZlVHlwZVByb3RvKTtcbiAgICBjb25zdCBjdXJ2ZU5hbWUgPSBFbGxpcHRpY0N1cnZlcy5jdXJ2ZVRvU3RyaW5nKGN1cnZlVHlwZVN1YnRsZSk7XG4gICAgY29uc3Qga2V5UGFpciA9IGF3YWl0IEVsbGlwdGljQ3VydmVzLmdlbmVyYXRlS2V5UGFpcignRUNESCcsIGN1cnZlTmFtZSk7XG4gICAgY29uc3QganNvblB1YmxpY0tleSA9XG4gICAgICAgIGF3YWl0IEVsbGlwdGljQ3VydmVzLmV4cG9ydENyeXB0b0tleShrZXlQYWlyLnB1YmxpY0tleSEpO1xuICAgIGNvbnN0IGpzb25Qcml2YXRlS2V5ID1cbiAgICAgICAgYXdhaXQgRWxsaXB0aWNDdXJ2ZXMuZXhwb3J0Q3J5cHRvS2V5KGtleVBhaXIucHJpdmF0ZUtleSEpO1xuICAgIHJldHVybiBFY2llc0FlYWRIa2RmUHJpdmF0ZUtleUZhY3RvcnkuanNvblRvUHJvdG9LZXkoXG4gICAgICAgIGpzb25Qcml2YXRlS2V5LCBqc29uUHVibGljS2V5LCBwYXJhbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqL1xuICBhc3luYyBuZXdLZXlEYXRhKHNlcmlhbGl6ZWRLZXlGb3JtYXQ6IFBiTWVzc2FnZXxcbiAgICAgICAgICAgICAgICAgICBVaW50OEFycmF5KTogUHJvbWlzZTxQYktleURhdGE+IHtcbiAgICBjb25zdCBrZXkgPSBhd2FpdCB0aGlzLm5ld0tleShzZXJpYWxpemVkS2V5Rm9ybWF0KTtcbiAgICBjb25zdCBrZXlEYXRhID1cbiAgICAgICAgKG5ldyBQYktleURhdGEoKSlcbiAgICAgICAgICAgIC5zZXRUeXBlVXJsKEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSlcbiAgICAgICAgICAgIC5zZXRWYWx1ZShrZXkuc2VyaWFsaXplQmluYXJ5KCkpXG4gICAgICAgICAgICAuc2V0S2V5TWF0ZXJpYWxUeXBlKFBiS2V5RGF0YS5LZXlNYXRlcmlhbFR5cGUuQVNZTU1FVFJJQ19QUklWQVRFKTtcbiAgICByZXR1cm4ga2V5RGF0YTtcbiAgfVxuXG4gIGdldFB1YmxpY0tleURhdGEoc2VyaWFsaXplZFByaXZhdGVLZXk6IFVpbnQ4QXJyYXkpIHtcbiAgICBjb25zdCBwcml2YXRlS2V5ID0gZGVzZXJpYWxpemVQcml2YXRlS2V5KHNlcmlhbGl6ZWRQcml2YXRlS2V5KTtcbiAgICBjb25zdCBwdWJsaWNLZXkgPSBwcml2YXRlS2V5LmdldFB1YmxpY0tleSgpO1xuICAgIGlmICghcHVibGljS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1B1YmxpYyBrZXkgbm90IHNldCcpO1xuICAgIH1cbiAgICBjb25zdCBwdWJsaWNLZXlEYXRhID1cbiAgICAgICAgKG5ldyBQYktleURhdGEoKSlcbiAgICAgICAgICAgIC5zZXRWYWx1ZShwdWJsaWNLZXkuc2VyaWFsaXplQmluYXJ5KCkpXG4gICAgICAgICAgICAuc2V0VHlwZVVybChFY2llc0FlYWRIa2RmUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRSlcbiAgICAgICAgICAgIC5zZXRLZXlNYXRlcmlhbFR5cGUoUGJLZXlEYXRhLktleU1hdGVyaWFsVHlwZS5BU1lNTUVUUklDX1BVQkxJQyk7XG4gICAgcmV0dXJuIHB1YmxpY0tleURhdGE7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHByaXZhdGUga2V5IHByb3RvIGNvcnJlc3BvbmRpbmcgdG8gZ2l2ZW4gSlNPTiBrZXkgcGFpciBhbmQgd2l0aFxuICAgKiB0aGUgZ2l2ZW4gcGFyYW1zLlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMganNvblRvUHJvdG9LZXkoXG4gICAgICBqc29uUHJpdmF0ZUtleTogSnNvbldlYktleSwganNvblB1YmxpY0tleTogSnNvbldlYktleSxcbiAgICAgIHBhcmFtczogUGJFY2llc0FlYWRIa2RmUGFyYW1zKTogUGJFY2llc0FlYWRIa2RmUHJpdmF0ZUtleSB7XG4gICAgY29uc3Qge3gsIHl9ID0ganNvblB1YmxpY0tleTtcbiAgICBpZiAoeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ3ggbXVzdCBiZSBzZXQnKTtcbiAgICB9XG4gICAgaWYgKHkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKCd5IG11c3QgYmUgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IHB1YmxpY0tleVByb3RvID1cbiAgICAgICAgKG5ldyBQYkVjaWVzQWVhZEhrZGZQdWJsaWNLZXkoKSlcbiAgICAgICAgICAgIC5zZXRWZXJzaW9uKEVjaWVzQWVhZEhrZGZQdWJsaWNLZXlNYW5hZ2VyLlZFUlNJT04pXG4gICAgICAgICAgICAuc2V0UGFyYW1zKHBhcmFtcylcbiAgICAgICAgICAgIC5zZXRYKEJ5dGVzLmZyb21CYXNlNjQoeCwgdHJ1ZSkpXG4gICAgICAgICAgICAuc2V0WShCeXRlcy5mcm9tQmFzZTY0KHksIHRydWUpKTtcbiAgICBjb25zdCB7ZH0gPSBqc29uUHJpdmF0ZUtleTtcbiAgICBpZiAoZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ2QgbXVzdCBiZSBzZXQnKTtcbiAgICB9XG4gICAgY29uc3QgcHJpdmF0ZUtleVByb3RvID0gKG5ldyBQYkVjaWVzQWVhZEhrZGZQcml2YXRlS2V5KCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRWZXJzaW9uKFZFUlNJT04pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRQdWJsaWNLZXkocHVibGljS2V5UHJvdG8pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRLZXlWYWx1ZShCeXRlcy5mcm9tQmFzZTY0KGQsIHRydWUpKTtcbiAgICByZXR1cm4gcHJpdmF0ZUtleVByb3RvO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnB1dCBrZXlGb3JtYXQgaXMgZWl0aGVyIGRlc2VyaWFsaXplZCAoaW4gY2FzZSB0aGF0IHRoZSBpbnB1dCBpc1xuICAgKiBVaW50OEFycmF5KSBvciBjaGVja2VkIHRvIGJlIGFuIEVjaWVzQWVhZEhrZGZLZXlGb3JtYXQtcHJvdG8gKG90aGVyd2lzZSkuXG4gICAqXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBnZXRLZXlGb3JtYXRQcm90byhrZXlGb3JtYXQ6IFBiTWVzc2FnZXxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVWludDhBcnJheSk6IFBiRWNpZXNBZWFkSGtkZktleUZvcm1hdCB7XG4gICAgaWYgKGtleUZvcm1hdCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgIHJldHVybiBFY2llc0FlYWRIa2RmUHJpdmF0ZUtleUZhY3RvcnkuZGVzZXJpYWxpemVLZXlGb3JtYXQoa2V5Rm9ybWF0KTtcbiAgICB9IGVsc2UgaWYgKGtleUZvcm1hdCBpbnN0YW5jZW9mIFBiRWNpZXNBZWFkSGtkZktleUZvcm1hdCkge1xuICAgICAgcmV0dXJuIGtleUZvcm1hdDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdFeHBlY3RlZCAnICsgRWNpZXNBZWFkSGtkZlByaXZhdGVLZXlNYW5hZ2VyLktFWV9UWVBFICtcbiAgICAgICAgICAnIGtleSBmb3JtYXQgcHJvdG8uJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZGVzZXJpYWxpemVLZXlGb3JtYXQoa2V5Rm9ybWF0OiBVaW50OEFycmF5KTpcbiAgICAgIFBiRWNpZXNBZWFkSGtkZktleUZvcm1hdCB7XG4gICAgbGV0IGtleUZvcm1hdFByb3RvOiBQYkVjaWVzQWVhZEhrZGZLZXlGb3JtYXQ7XG4gICAgdHJ5IHtcbiAgICAgIGtleUZvcm1hdFByb3RvID0gUGJFY2llc0FlYWRIa2RmS2V5Rm9ybWF0LmRlc2VyaWFsaXplQmluYXJ5KGtleUZvcm1hdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdJbnB1dCBjYW5ub3QgYmUgcGFyc2VkIGFzICcgK1xuICAgICAgICAgIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArICcga2V5IGZvcm1hdCBwcm90by4nKTtcbiAgICB9XG4gICAgaWYgKCFrZXlGb3JtYXRQcm90by5nZXRQYXJhbXMoKSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdJbnB1dCBjYW5ub3QgYmUgcGFyc2VkIGFzICcgK1xuICAgICAgICAgIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArICcga2V5IGZvcm1hdCBwcm90by4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGtleUZvcm1hdFByb3RvO1xuICB9XG59XG5cbi8qKlxuICogQGZpbmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBFY2llc0FlYWRIa2RmUHJpdmF0ZUtleU1hbmFnZXIgaW1wbGVtZW50c1xuICAgIEtleU1hbmFnZXIuS2V5TWFuYWdlcjxIeWJyaWREZWNyeXB0PiB7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFNVUFBPUlRFRF9QUklNSVRJVkUgPSBIeWJyaWREZWNyeXB0O1xuICBzdGF0aWMgS0VZX1RZUEU6IHN0cmluZyA9XG4gICAgICAndHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuRWNpZXNBZWFkSGtkZlByaXZhdGVLZXknO1xuICBrZXlGYWN0b3J5ID0gbmV3IEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5RmFjdG9yeSgpO1xuXG4gIGFzeW5jIGdldFByaW1pdGl2ZShcbiAgICAgIHByaW1pdGl2ZVR5cGU6IFV0aWwuQ29uc3RydWN0b3I8SHlicmlkRGVjcnlwdD4sXG4gICAgICBrZXk6IFBiS2V5RGF0YXxQYk1lc3NhZ2UpIHtcbiAgICBpZiAocHJpbWl0aXZlVHlwZSAhPT0gdGhpcy5nZXRQcmltaXRpdmVUeXBlKCkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnUmVxdWVzdGVkIHByaW1pdGl2ZSB0eXBlIHdoaWNoIGlzIG5vdCAnICtcbiAgICAgICAgICAnc3VwcG9ydGVkIGJ5IHRoaXMga2V5IG1hbmFnZXIuJyk7XG4gICAgfVxuICAgIGNvbnN0IGtleVByb3RvID0gRWNpZXNBZWFkSGtkZlByaXZhdGVLZXlNYW5hZ2VyLmdldEtleVByb3RvKGtleSk7XG4gICAgRWNpZXNBZWFkSGtkZlZhbGlkYXRvcnMudmFsaWRhdGVQcml2YXRlS2V5KFxuICAgICAgICBrZXlQcm90bywgVkVSU0lPTiwgRWNpZXNBZWFkSGtkZlB1YmxpY0tleU1hbmFnZXIuVkVSU0lPTik7XG4gICAgY29uc3QgcmVjZXBpZW50UHJpdmF0ZUtleSA9XG4gICAgICAgIEVjaWVzQWVhZEhrZGZVdGlsLmdldEpzb25XZWJLZXlGcm9tUHJvdG8oa2V5UHJvdG8pO1xuICAgIGNvbnN0IHB1YmxpY0tleSA9IGtleVByb3RvLmdldFB1YmxpY0tleSgpO1xuICAgIGlmICghcHVibGljS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1B1YmxpYyBrZXkgbm90IHNldCcpO1xuICAgIH1cbiAgICBjb25zdCBwYXJhbXMgPSBwdWJsaWNLZXkuZ2V0UGFyYW1zKCk7XG4gICAgaWYgKCFwYXJhbXMpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignUGFyYW1zIG5vdCBzZXQnKTtcbiAgICB9XG4gICAgY29uc3QgZGVtUGFyYW1zID0gcGFyYW1zLmdldERlbVBhcmFtcygpO1xuICAgIGlmICghZGVtUGFyYW1zKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0RFTSBwYXJhbXMgbm90IHNldCcpO1xuICAgIH1cbiAgICBjb25zdCBrZXlUZW1wbGF0ZSA9IChkZW1QYXJhbXMuZ2V0QWVhZERlbSgpKTtcbiAgICBpZiAoIWtleVRlbXBsYXRlKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0tleSB0ZW1wbGF0ZSBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGRlbUhlbHBlciA9IG5ldyBSZWdpc3RyeUVjaWVzQWVhZEhrZGZEZW1IZWxwZXIoa2V5VGVtcGxhdGUpO1xuICAgIGNvbnN0IHBvaW50Rm9ybWF0ID1cbiAgICAgICAgVXRpbC5wb2ludEZvcm1hdFByb3RvVG9TdWJ0bGUocGFyYW1zLmdldEVjUG9pbnRGb3JtYXQoKSk7XG4gICAgY29uc3Qga2VtUGFyYW1zID0gcGFyYW1zLmdldEtlbVBhcmFtcygpO1xuICAgIGlmICgha2VtUGFyYW1zKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0tFTSBwYXJhbXMgbm90IHNldCcpO1xuICAgIH1cbiAgICBjb25zdCBoa2RmSGFzaCA9IFV0aWwuaGFzaFR5cGVQcm90b1RvU3RyaW5nKGtlbVBhcmFtcy5nZXRIa2RmSGFzaFR5cGUoKSk7XG4gICAgY29uc3QgaGtkZlNhbHQgPSBieXRlc0FzVTgoa2VtUGFyYW1zLmdldEhrZGZTYWx0KCkpO1xuICAgIHJldHVybiBlY2llc0FlYWRIa2RmSHlicmlkRGVjcnlwdC5mcm9tSnNvbldlYktleShcbiAgICAgICAgcmVjZXBpZW50UHJpdmF0ZUtleSwgaGtkZkhhc2gsIHBvaW50Rm9ybWF0LCBkZW1IZWxwZXIsIGhrZGZTYWx0KTtcbiAgfVxuXG4gIGRvZXNTdXBwb3J0KGtleVR5cGU6IHN0cmluZykge1xuICAgIHJldHVybiBrZXlUeXBlID09PSB0aGlzLmdldEtleVR5cGUoKTtcbiAgfVxuXG4gIGdldEtleVR5cGUoKSB7XG4gICAgcmV0dXJuIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRTtcbiAgfVxuXG4gIGdldFByaW1pdGl2ZVR5cGUoKSB7XG4gICAgcmV0dXJuIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5TVVBQT1JURURfUFJJTUlUSVZFO1xuICB9XG5cbiAgZ2V0VmVyc2lvbigpIHtcbiAgICByZXR1cm4gVkVSU0lPTjtcbiAgfVxuXG4gIGdldEtleUZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIHRoaXMua2V5RmFjdG9yeTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldEtleVByb3RvKGtleU1hdGVyaWFsOiBQYktleURhdGF8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBiTWVzc2FnZSk6IFBiRWNpZXNBZWFkSGtkZlByaXZhdGVLZXkge1xuICAgIGlmIChrZXlNYXRlcmlhbCBpbnN0YW5jZW9mIFBiS2V5RGF0YSkge1xuICAgICAgcmV0dXJuIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5nZXRLZXlQcm90b0Zyb21LZXlEYXRhKGtleU1hdGVyaWFsKTtcbiAgICB9XG4gICAgaWYgKGtleU1hdGVyaWFsIGluc3RhbmNlb2YgUGJFY2llc0FlYWRIa2RmUHJpdmF0ZUtleSkge1xuICAgICAgcmV0dXJuIGtleU1hdGVyaWFsO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICdLZXkgdHlwZSBpcyBub3Qgc3VwcG9ydGVkLiBUaGlzIGtleSAnICtcbiAgICAgICAgJ21hbmFnZXIgc3VwcG9ydHMgJyArIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArICcuJyk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRLZXlQcm90b0Zyb21LZXlEYXRhKGtleURhdGE6IFBiS2V5RGF0YSk6XG4gICAgICBQYkVjaWVzQWVhZEhrZGZQcml2YXRlS2V5IHtcbiAgICBpZiAoa2V5RGF0YS5nZXRUeXBlVXJsKCkgIT09IEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdLZXkgdHlwZSAnICsga2V5RGF0YS5nZXRUeXBlVXJsKCkgK1xuICAgICAgICAgICcgaXMgbm90IHN1cHBvcnRlZC4gVGhpcyBrZXkgbWFuYWdlciBzdXBwb3J0cyAnICtcbiAgICAgICAgICBFY2llc0FlYWRIa2RmUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUgKyAnLicpO1xuICAgIH1cbiAgICByZXR1cm4gZGVzZXJpYWxpemVQcml2YXRlS2V5KGtleURhdGEuZ2V0VmFsdWUoKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGVzZXJpYWxpemVQcml2YXRlS2V5KHNlcmlhbGl6ZWRQcml2YXRlS2V5OiBQcm90b0J5dGVzKTpcbiAgICBQYkVjaWVzQWVhZEhrZGZQcml2YXRlS2V5IHtcbiAgbGV0IGtleTogUGJFY2llc0FlYWRIa2RmUHJpdmF0ZUtleTtcbiAgdHJ5IHtcbiAgICBrZXkgPSBQYkVjaWVzQWVhZEhrZGZQcml2YXRlS2V5LmRlc2VyaWFsaXplQmluYXJ5KHNlcmlhbGl6ZWRQcml2YXRlS2V5KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArXG4gICAgICAgICcga2V5LXByb3RvLicpO1xuICB9XG4gIGlmICgha2V5LmdldFB1YmxpY0tleSgpIHx8ICFrZXkuZ2V0S2V5VmFsdWUoKSkge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEVjaWVzQWVhZEhrZGZQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArXG4gICAgICAgICcga2V5LXByb3RvLicpO1xuICB9XG4gIHJldHVybiBrZXk7XG59XG4iXX0=