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
JavaScript
/**
* @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=