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.
117 lines • 13.7 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 { PbHpkePublicKey, PbKeyData } from '../../../internal/proto';
import { HybridEncrypt } from '../hybrid_encrypt';
import { HpkeEncrypt } from './hpke_encrypt';
import * as hpkeValidators from './hpke_validators';
/**
* This class corresponds to the 'HpkePrivateKeyFactory', but it does not
* support key generation. The 'HpkePrivateKeyFactor'y' should be use to
* generate new HPKE key pairs.
* @final
*/
class HpkePublicKeyFactory {
newKey(keyFormat) {
throw new SecurityException('This operation is not supported for public keys. ' +
'Use HpkePrivateKeyManager to generate new keys.');
}
newKeyData(serializedKeyFormat) {
throw new SecurityException('This operation is not supported for public keys. ' +
'Use HpkePrivateKeyManager to generate new keys.');
}
}
/**
* Key manager that produces new instances of {@link HpkeEncrypt} primitives.
* @final
*/
export class HpkePublicKeyManager {
constructor() {
this.keyFactory = new HpkePublicKeyFactory();
}
/**
* Constructs an instance of the 'HybridEncrypt' primitive for a given HPKE
* public 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 = HpkePublicKeyManager.getKeyProto(key);
hpkeValidators.validatePublicKey(keyProto, this.getVersion());
return HpkeEncrypt.createHpkeEncrypt(keyProto);
});
}
/** Returns true if this KeyManager supports 'HpkePublicKey' key type. */
doesSupport(keyType) {
return keyType === this.getKeyType();
}
/** Returns the URL which identifies the keys managed by this KeyManager. */
getKeyType() {
return HpkePublicKeyManager.KEY_TYPE;
}
/**
* Returns the type of primitive which can be generated by this KeyManager,
* i.e. 'HybridEncrypt'
*/
getPrimitiveType() {
return HpkePublicKeyManager.SUPPORTED_PRIMITIVE;
}
getVersion() {
return HpkePublicKeyManager.VERSION;
}
getKeyFactory() {
return this.keyFactory;
}
static getKeyProto(keyMaterial) {
if (keyMaterial instanceof PbKeyData) {
return HpkePublicKeyManager.getKeyProtoFromKeyData(keyMaterial);
}
if (keyMaterial instanceof PbHpkePublicKey) {
return keyMaterial;
}
throw new SecurityException('Key type is not supported. This key manager supports ' +
HpkePublicKeyManager.KEY_TYPE + '.');
}
static getKeyProtoFromKeyData(keyData) {
if (keyData.getTypeUrl() !== HpkePublicKeyManager.KEY_TYPE) {
throw new SecurityException('Key type ' + keyData.getTypeUrl() + ' is not supported. This key ' +
'manager supports ' + HpkePublicKeyManager.KEY_TYPE + '.');
}
let key;
try {
key = PbHpkePublicKey.deserializeBinary(keyData.getValue());
}
catch (e) {
throw new SecurityException('Input cannot be parsed as ' + HpkePublicKeyManager.KEY_TYPE +
' key-proto.');
}
/**
* Throws the same generic error to avoid discrepancies between different
* versions.
*/
if (!key.getParams() || !key.getPublicKey()) {
throw new SecurityException('Input cannot be parsed as ' + HpkePublicKeyManager.KEY_TYPE +
' key-proto.');
}
return key;
}
}
HpkePublicKeyManager.KEY_TYPE = 'type.googleapis.com/google.crypto.tink.HpkePublicKey';
HpkePublicKeyManager.SUPPORTED_PRIMITIVE = HybridEncrypt;
HpkePublicKeyManager.VERSION = 0;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHBrZV9wdWJsaWNfa2V5X21hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9oeWJyaWQvaW50ZXJuYWwvaHBrZS9ocGtlX3B1YmxpY19rZXlfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHOzs7Ozs7Ozs7O0FBRUgsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sdUNBQXVDLENBQUM7QUFFeEUsT0FBTyxFQUFDLGVBQWUsRUFBRSxTQUFTLEVBQVksTUFBTSx5QkFBeUIsQ0FBQztBQUU5RSxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFFaEQsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sS0FBSyxjQUFjLE1BQU0sbUJBQW1CLENBQUM7QUFFcEQ7Ozs7O0dBS0c7QUFDSCxNQUFNLG9CQUFvQjtJQUN4QixNQUFNLENBQUMsU0FBK0I7UUFDcEMsTUFBTSxJQUFJLGlCQUFpQixDQUN2QixtREFBbUQ7WUFDbkQsaURBQWlELENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQsVUFBVSxDQUFDLG1CQUErQjtRQUN4QyxNQUFNLElBQUksaUJBQWlCLENBQ3ZCLG1EQUFtRDtZQUNuRCxpREFBaUQsQ0FBQyxDQUFDO0lBQ3pELENBQUM7Q0FDRjtBQUVEOzs7R0FHRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFBakM7UUFLRSxlQUFVLEdBQUcsSUFBSSxvQkFBb0IsRUFBRSxDQUFDO0lBK0UxQyxDQUFDO0lBOUVDOzs7T0FHRztJQUNHLFlBQVksQ0FDZCxhQUE4QyxFQUM5QyxHQUF3Qjs7WUFDMUIsSUFBSSxhQUFhLEtBQUssSUFBSSxDQUFDLGdCQUFnQixFQUFFLEVBQUU7Z0JBQzdDLE1BQU0sSUFBSSxpQkFBaUIsQ0FDdkIsd0NBQXdDO29CQUN4QyxnQ0FBZ0MsQ0FBQyxDQUFDO2FBQ3ZDO1lBQ0QsTUFBTSxRQUFRLEdBQW9CLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN4RSxjQUFjLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1lBQzlELE9BQU8sV0FBVyxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELENBQUM7S0FBQTtJQUNELHlFQUF5RTtJQUN6RSxXQUFXLENBQUMsT0FBZTtRQUN6QixPQUFPLE9BQU8sS0FBSyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDdkMsQ0FBQztJQUNELDRFQUE0RTtJQUM1RSxVQUFVO1FBQ1IsT0FBTyxvQkFBb0IsQ0FBQyxRQUFRLENBQUM7SUFDdkMsQ0FBQztJQUNEOzs7T0FHRztJQUNILGdCQUFnQjtRQUNkLE9BQU8sb0JBQW9CLENBQUMsbUJBQW1CLENBQUM7SUFDbEQsQ0FBQztJQUVELFVBQVU7UUFDUixPQUFPLG9CQUFvQixDQUFDLE9BQU8sQ0FBQztJQUN0QyxDQUFDO0lBRUQsYUFBYTtRQUNYLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO0lBRU8sTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUNTO1FBQ2xDLElBQUksV0FBVyxZQUFZLFNBQVMsRUFBRTtZQUNwQyxPQUFPLG9CQUFvQixDQUFDLHNCQUFzQixDQUFDLFdBQVcsQ0FBQyxDQUFDO1NBQ2pFO1FBQ0QsSUFBSSxXQUFXLFlBQVksZUFBZSxFQUFFO1lBQzFDLE9BQU8sV0FBVyxDQUFDO1NBQ3BCO1FBQ0QsTUFBTSxJQUFJLGlCQUFpQixDQUN2Qix1REFBdUQ7WUFDdkQsb0JBQW9CLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFTyxNQUFNLENBQUMsc0JBQXNCLENBQUMsT0FBa0I7UUFDdEQsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLEtBQUssb0JBQW9CLENBQUMsUUFBUSxFQUFFO1lBQzFELE1BQU0sSUFBSSxpQkFBaUIsQ0FDdkIsV0FBVyxHQUFHLE9BQU8sQ0FBQyxVQUFVLEVBQUUsR0FBRyw4QkFBOEI7Z0JBQ25FLG1CQUFtQixHQUFHLG9CQUFvQixDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsQ0FBQztTQUNoRTtRQUNELElBQUksR0FBb0IsQ0FBQztRQUN6QixJQUFJO1lBQ0YsR0FBRyxHQUFHLGVBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztTQUM3RDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsTUFBTSxJQUFJLGlCQUFpQixDQUN2Qiw0QkFBNEIsR0FBRyxvQkFBb0IsQ0FBQyxRQUFRO2dCQUM1RCxhQUFhLENBQUMsQ0FBQztTQUNwQjtRQUNEOzs7V0FHRztRQUNILElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDM0MsTUFBTSxJQUFJLGlCQUFpQixDQUN2Qiw0QkFBNEIsR0FBRyxvQkFBb0IsQ0FBQyxRQUFRO2dCQUM1RCxhQUFhLENBQUMsQ0FBQztTQUNwQjtRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQzs7QUFqRk0sNkJBQVEsR0FBRyxzREFBc0QsQ0FBQztBQUNqRCx3Q0FBbUIsR0FBRyxhQUFhLENBQUM7QUFDckQsNEJBQU8sR0FBRyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCB7U2VjdXJpdHlFeGNlcHRpb259IGZyb20gJy4uLy4uLy4uL2V4Y2VwdGlvbi9zZWN1cml0eV9leGNlcHRpb24nO1xuaW1wb3J0ICogYXMga2V5TWFuYWdlciBmcm9tICcuLi8uLi8uLi9pbnRlcm5hbC9rZXlfbWFuYWdlcic7XG5pbXBvcnQge1BiSHBrZVB1YmxpY0tleSwgUGJLZXlEYXRhLCBQYk1lc3NhZ2V9IGZyb20gJy4uLy4uLy4uL2ludGVybmFsL3Byb3RvJztcbmltcG9ydCAqIGFzIHV0aWwgZnJvbSAnLi4vLi4vLi4vaW50ZXJuYWwvdXRpbCc7XG5pbXBvcnQge0h5YnJpZEVuY3J5cHR9IGZyb20gJy4uL2h5YnJpZF9lbmNyeXB0JztcblxuaW1wb3J0IHtIcGtlRW5jcnlwdH0gZnJvbSAnLi9ocGtlX2VuY3J5cHQnO1xuaW1wb3J0ICogYXMgaHBrZVZhbGlkYXRvcnMgZnJvbSAnLi9ocGtlX3ZhbGlkYXRvcnMnO1xuXG4vKipcbiAqIFRoaXMgY2xhc3MgY29ycmVzcG9uZHMgdG8gdGhlICdIcGtlUHJpdmF0ZUtleUZhY3RvcnknLCBidXQgaXQgZG9lcyBub3RcbiAqIHN1cHBvcnQga2V5IGdlbmVyYXRpb24uIFRoZSAnSHBrZVByaXZhdGVLZXlGYWN0b3IneScgc2hvdWxkIGJlIHVzZSB0b1xuICogZ2VuZXJhdGUgbmV3IEhQS0Uga2V5IHBhaXJzLlxuICogQGZpbmFsXG4gKi9cbmNsYXNzIEhwa2VQdWJsaWNLZXlGYWN0b3J5IGltcGxlbWVudHMga2V5TWFuYWdlci5LZXlGYWN0b3J5IHtcbiAgbmV3S2V5KGtleUZvcm1hdDogUGJNZXNzYWdlfFVpbnQ4QXJyYXkpOiBuZXZlciB7XG4gICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAnVGhpcyBvcGVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCBmb3IgcHVibGljIGtleXMuICcgK1xuICAgICAgICAnVXNlIEhwa2VQcml2YXRlS2V5TWFuYWdlciB0byBnZW5lcmF0ZSBuZXcga2V5cy4nKTtcbiAgfVxuXG4gIG5ld0tleURhdGEoc2VyaWFsaXplZEtleUZvcm1hdDogVWludDhBcnJheSk6IG5ldmVyIHtcbiAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICdUaGlzIG9wZXJhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIGZvciBwdWJsaWMga2V5cy4gJyArXG4gICAgICAgICdVc2UgSHBrZVByaXZhdGVLZXlNYW5hZ2VyIHRvIGdlbmVyYXRlIG5ldyBrZXlzLicpO1xuICB9XG59XG5cbi8qKlxuICogS2V5IG1hbmFnZXIgdGhhdCBwcm9kdWNlcyBuZXcgaW5zdGFuY2VzIG9mIHtAbGluayBIcGtlRW5jcnlwdH0gcHJpbWl0aXZlcy5cbiAqIEBmaW5hbFxuICovXG5leHBvcnQgY2xhc3MgSHBrZVB1YmxpY0tleU1hbmFnZXIgaW1wbGVtZW50c1xuICAgIGtleU1hbmFnZXIuS2V5TWFuYWdlcjxIeWJyaWRFbmNyeXB0PiB7XG4gIHN0YXRpYyBLRVlfVFlQRSA9ICd0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5IcGtlUHVibGljS2V5JztcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgU1VQUE9SVEVEX1BSSU1JVElWRSA9IEh5YnJpZEVuY3J5cHQ7XG4gIHN0YXRpYyBWRVJTSU9OID0gMDtcbiAga2V5RmFjdG9yeSA9IG5ldyBIcGtlUHVibGljS2V5RmFjdG9yeSgpO1xuICAvKipcbiAgICogQ29uc3RydWN0cyBhbiBpbnN0YW5jZSBvZiB0aGUgJ0h5YnJpZEVuY3J5cHQnIHByaW1pdGl2ZSBmb3IgYSBnaXZlbiBIUEtFXG4gICAqIHB1YmxpYyBrZXkuXG4gICAqL1xuICBhc3luYyBnZXRQcmltaXRpdmUoXG4gICAgICBwcmltaXRpdmVUeXBlOiB1dGlsLkNvbnN0cnVjdG9yPEh5YnJpZEVuY3J5cHQ+LFxuICAgICAga2V5OiBQYktleURhdGF8UGJNZXNzYWdlKSB7XG4gICAgaWYgKHByaW1pdGl2ZVR5cGUgIT09IHRoaXMuZ2V0UHJpbWl0aXZlVHlwZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ1JlcXVlc3RlZCBwcmltaXRpdmUgdHlwZSB3aGljaCBpcyBub3QgJyArXG4gICAgICAgICAgJ3N1cHBvcnRlZCBieSB0aGlzIGtleSBtYW5hZ2VyLicpO1xuICAgIH1cbiAgICBjb25zdCBrZXlQcm90bzogUGJIcGtlUHVibGljS2V5ID0gSHBrZVB1YmxpY0tleU1hbmFnZXIuZ2V0S2V5UHJvdG8oa2V5KTtcbiAgICBocGtlVmFsaWRhdG9ycy52YWxpZGF0ZVB1YmxpY0tleShrZXlQcm90bywgdGhpcy5nZXRWZXJzaW9uKCkpO1xuICAgIHJldHVybiBIcGtlRW5jcnlwdC5jcmVhdGVIcGtlRW5jcnlwdChrZXlQcm90byk7XG4gIH1cbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIEtleU1hbmFnZXIgc3VwcG9ydHMgJ0hwa2VQdWJsaWNLZXknIGtleSB0eXBlLiAqL1xuICBkb2VzU3VwcG9ydChrZXlUeXBlOiBzdHJpbmcpIHtcbiAgICByZXR1cm4ga2V5VHlwZSA9PT0gdGhpcy5nZXRLZXlUeXBlKCk7XG4gIH1cbiAgLyoqIFJldHVybnMgdGhlIFVSTCB3aGljaCBpZGVudGlmaWVzIHRoZSBrZXlzIG1hbmFnZWQgYnkgdGhpcyBLZXlNYW5hZ2VyLiAqL1xuICBnZXRLZXlUeXBlKCkge1xuICAgIHJldHVybiBIcGtlUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRTtcbiAgfVxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdHlwZSBvZiBwcmltaXRpdmUgd2hpY2ggY2FuIGJlIGdlbmVyYXRlZCBieSB0aGlzIEtleU1hbmFnZXIsXG4gICAqIGkuZS4gJ0h5YnJpZEVuY3J5cHQnXG4gICAqL1xuICBnZXRQcmltaXRpdmVUeXBlKCkge1xuICAgIHJldHVybiBIcGtlUHVibGljS2V5TWFuYWdlci5TVVBQT1JURURfUFJJTUlUSVZFO1xuICB9XG5cbiAgZ2V0VmVyc2lvbigpIHtcbiAgICByZXR1cm4gSHBrZVB1YmxpY0tleU1hbmFnZXIuVkVSU0lPTjtcbiAgfVxuXG4gIGdldEtleUZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIHRoaXMua2V5RmFjdG9yeTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldEtleVByb3RvKGtleU1hdGVyaWFsOiBQYktleURhdGF8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBiTWVzc2FnZSk6IFBiSHBrZVB1YmxpY0tleSB7XG4gICAgaWYgKGtleU1hdGVyaWFsIGluc3RhbmNlb2YgUGJLZXlEYXRhKSB7XG4gICAgICByZXR1cm4gSHBrZVB1YmxpY0tleU1hbmFnZXIuZ2V0S2V5UHJvdG9Gcm9tS2V5RGF0YShrZXlNYXRlcmlhbCk7XG4gICAgfVxuICAgIGlmIChrZXlNYXRlcmlhbCBpbnN0YW5jZW9mIFBiSHBrZVB1YmxpY0tleSkge1xuICAgICAgcmV0dXJuIGtleU1hdGVyaWFsO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICdLZXkgdHlwZSBpcyBub3Qgc3VwcG9ydGVkLiBUaGlzIGtleSBtYW5hZ2VyIHN1cHBvcnRzICcgK1xuICAgICAgICBIcGtlUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRSArICcuJyk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRLZXlQcm90b0Zyb21LZXlEYXRhKGtleURhdGE6IFBiS2V5RGF0YSk6IFBiSHBrZVB1YmxpY0tleSB7XG4gICAgaWYgKGtleURhdGEuZ2V0VHlwZVVybCgpICE9PSBIcGtlUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdLZXkgdHlwZSAnICsga2V5RGF0YS5nZXRUeXBlVXJsKCkgKyAnIGlzIG5vdCBzdXBwb3J0ZWQuIFRoaXMga2V5ICcgK1xuICAgICAgICAgICdtYW5hZ2VyIHN1cHBvcnRzICcgKyBIcGtlUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRSArICcuJyk7XG4gICAgfVxuICAgIGxldCBrZXk6IFBiSHBrZVB1YmxpY0tleTtcbiAgICB0cnkge1xuICAgICAga2V5ID0gUGJIcGtlUHVibGljS2V5LmRlc2VyaWFsaXplQmluYXJ5KGtleURhdGEuZ2V0VmFsdWUoKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdJbnB1dCBjYW5ub3QgYmUgcGFyc2VkIGFzICcgKyBIcGtlUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRSArXG4gICAgICAgICAgJyBrZXktcHJvdG8uJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRocm93cyB0aGUgc2FtZSBnZW5lcmljIGVycm9yIHRvIGF2b2lkIGRpc2NyZXBhbmNpZXMgYmV0d2VlbiBkaWZmZXJlbnRcbiAgICAgKiB2ZXJzaW9ucy5cbiAgICAgKi9cbiAgICBpZiAoIWtleS5nZXRQYXJhbXMoKSB8fCAha2V5LmdldFB1YmxpY0tleSgpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEhwa2VQdWJsaWNLZXlNYW5hZ2VyLktFWV9UWVBFICtcbiAgICAgICAgICAnIGtleS1wcm90by4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGtleTtcbiAgfVxufVxuIl19