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