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.

259 lines 34.2 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 { PbAesCtrHmacAeadKey, PbAesCtrHmacAeadKeyFormat, PbAesCtrKey, PbAesCtrKeyFormat, PbHashType, PbHmacKey, PbHmacKeyFormat, PbKeyData } from '../internal/proto'; import { bytesAsU8, bytesLength } from '../internal/proto_shims'; import * as Registry from '../internal/registry'; import { aesCtrHmacFromRawKeys } from '../subtle/encrypt_then_authenticate'; import * as Random from '../subtle/random'; import * as Validators from '../subtle/validators'; import { Aead } from './internal/aead'; /** * @final */ class AesCtrHmacAeadKeyFactory { /** */ newKey(keyFormat) { let keyFormatProto; if (keyFormat instanceof Uint8Array) { try { keyFormatProto = PbAesCtrHmacAeadKeyFormat.deserializeBinary(keyFormat); } catch (e) { throw new SecurityException('Could not parse the given Uint8Array as a serialized proto of ' + AesCtrHmacAeadKeyManager.KEY_TYPE); } if (!keyFormatProto || !keyFormatProto.getAesCtrKeyFormat() || !keyFormatProto.getHmacKeyFormat()) { throw new SecurityException('Could not parse the given Uint8Array as a serialized proto of ' + AesCtrHmacAeadKeyManager.KEY_TYPE); } } else if (keyFormat instanceof PbAesCtrHmacAeadKeyFormat) { keyFormatProto = keyFormat; } else { throw new SecurityException('Expected AesCtrHmacAeadKeyFormat-proto'); } const { aesCtrParams, aesCtrKeySize } = this.validateAesCtrKeyFormat(keyFormatProto.getAesCtrKeyFormat()); const aesCtrKey = (new PbAesCtrKey()) .setVersion(AesCtrHmacAeadKeyFactory.VERSION) .setParams(aesCtrParams) .setKeyValue(Random.randBytes(aesCtrKeySize)); const { hmacParams, hmacKeySize } = this.validateHmacKeyFormat(keyFormatProto.getHmacKeyFormat()); const hmacKey = (new PbHmacKey()) .setVersion(AesCtrHmacAeadKeyFactory.VERSION) .setParams(hmacParams) .setKeyValue(Random.randBytes(hmacKeySize)); const aesCtrHmacAeadKey = (new PbAesCtrHmacAeadKey()).setAesCtrKey(aesCtrKey).setHmacKey(hmacKey); return aesCtrHmacAeadKey; } /** */ newKeyData(serializedKeyFormat) { const key = (this.newKey(serializedKeyFormat)); const keyData = (new PbKeyData()) .setTypeUrl(AesCtrHmacAeadKeyManager.KEY_TYPE) .setValue(key.serializeBinary()) .setKeyMaterialType(PbKeyData.KeyMaterialType.SYMMETRIC); return keyData; } // helper functions /** * Checks the parameters and size of a given keyFormat. * */ validateAesCtrKeyFormat(keyFormat) { if (!keyFormat) { throw new SecurityException('Invalid AES CTR HMAC key format: key format undefined'); } const aesCtrKeySize = keyFormat.getKeySize(); Validators.validateAesKeySize(aesCtrKeySize); const aesCtrParams = keyFormat.getParams(); if (!aesCtrParams) { throw new SecurityException('Invalid AES CTR HMAC key format: params undefined'); } const ivSize = aesCtrParams.getIvSize(); if (ivSize < AesCtrHmacAeadKeyFactory.MIN_IV_SIZE || ivSize > AesCtrHmacAeadKeyFactory.MAX_IV_SIZE) { throw new SecurityException('Invalid AES CTR HMAC key format: IV size is out of range: ' + ivSize); } return { aesCtrParams, aesCtrKeySize, ivSize }; } /** * Checks the parameters and size of a given keyFormat. * */ validateHmacKeyFormat(keyFormat) { if (!keyFormat) { throw new SecurityException('Invalid AES CTR HMAC key format: key format undefined'); } const hmacKeySize = keyFormat.getKeySize(); if (hmacKeySize < AesCtrHmacAeadKeyFactory.MIN_KEY_SIZE) { throw new SecurityException('Invalid AES CTR HMAC key format: HMAC key is too small: ' + keyFormat.getKeySize()); } const hmacParams = keyFormat.getParams(); if (!hmacParams) { throw new SecurityException('Invalid AES CTR HMAC key format: params undefined'); } const tagSize = hmacParams.getTagSize(); if (tagSize < AesCtrHmacAeadKeyFactory.MIN_TAG_SIZE) { throw new SecurityException('Invalid HMAC params: tag size ' + tagSize + ' is too small.'); } if (!AesCtrHmacAeadKeyFactory.MAX_TAG_SIZE.has(hmacParams.getHash())) { throw new SecurityException('Unknown hash type.'); } else if (tagSize > AesCtrHmacAeadKeyFactory.MAX_TAG_SIZE.get(hmacParams.getHash())) { throw new SecurityException('Invalid HMAC params: tag size ' + tagSize + ' is out of range.'); } let hashType; switch (hmacParams.getHash()) { case PbHashType.SHA1: hashType = 'SHA-1'; break; case PbHashType.SHA256: hashType = 'SHA-256'; break; case PbHashType.SHA512: hashType = 'SHA-512'; break; default: hashType = 'UNKNOWN HASH'; } return { hmacParams, hmacKeySize, hashType, tagSize }; } } AesCtrHmacAeadKeyFactory.VERSION = 0; AesCtrHmacAeadKeyFactory.MIN_KEY_SIZE = 16; AesCtrHmacAeadKeyFactory.MIN_IV_SIZE = 12; AesCtrHmacAeadKeyFactory.MAX_IV_SIZE = 16; AesCtrHmacAeadKeyFactory.MIN_TAG_SIZE = 10; AesCtrHmacAeadKeyFactory.MAX_TAG_SIZE = new Map([ [PbHashType.SHA1, 20], [PbHashType.SHA256, 32], [PbHashType.SHA512, 64] ]); /** * @final */ export class AesCtrHmacAeadKeyManager { constructor() { this.keyFactory = new AesCtrHmacAeadKeyFactory(); } /** */ 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.'); } let deserializedKey; if (key instanceof PbKeyData) { if (!this.doesSupport(key.getTypeUrl())) { throw new SecurityException('Key type ' + key.getTypeUrl() + ' is not supported. This key manager supports ' + this.getKeyType() + '.'); } try { deserializedKey = PbAesCtrHmacAeadKey.deserializeBinary(key.getValue()); } catch (e) { throw new SecurityException('Could not parse the key in key data as a serialized proto of ' + AesCtrHmacAeadKeyManager.KEY_TYPE); } if (deserializedKey === null || deserializedKey === undefined) { throw new SecurityException('Could not parse the key in key data as a serialized proto of ' + AesCtrHmacAeadKeyManager.KEY_TYPE); } } else if (key instanceof PbAesCtrHmacAeadKey) { deserializedKey = key; } else { throw new SecurityException('Given key type is not supported. ' + 'This key manager supports ' + this.getKeyType() + '.'); } const { aesCtrKeyValue, ivSize } = this.validateAesCtrKey(deserializedKey.getAesCtrKey()); const { hmacKeyValue, hashType, tagSize } = this.validateHmacKey(deserializedKey.getHmacKey()); return yield aesCtrHmacFromRawKeys(aesCtrKeyValue, ivSize, hashType, hmacKeyValue, tagSize); }); } /** */ doesSupport(keyType) { return keyType === this.getKeyType(); } /** */ getKeyType() { return AesCtrHmacAeadKeyManager.KEY_TYPE; } /** */ getPrimitiveType() { return AesCtrHmacAeadKeyManager.SUPPORTED_PRIMITIVE; } /** */ getVersion() { return AesCtrHmacAeadKeyManager.VERSION; } /** */ getKeyFactory() { return this.keyFactory; } // helper functions /** * Checks the parameters and size of a given AES-CTR key. * */ validateAesCtrKey(key) { if (!key) { throw new SecurityException('Invalid AES CTR HMAC key format: key undefined'); } Validators.validateVersion(key.getVersion(), this.getVersion()); const keyFormat = (new PbAesCtrKeyFormat()) .setParams(key.getParams()) .setKeySize(bytesLength(key.getKeyValue())); const { ivSize } = this.keyFactory.validateAesCtrKeyFormat(keyFormat); return { aesCtrKeyValue: bytesAsU8(key.getKeyValue()), ivSize }; } /** * Checks the parameters and size of a given HMAC key. * */ validateHmacKey(key) { if (!key) { throw new SecurityException('Invalid AES CTR HMAC key format: key undefined'); } Validators.validateVersion(key.getVersion(), this.getVersion()); const keyFormat = (new PbHmacKeyFormat()) .setParams(key.getParams()) .setKeySize(bytesLength(key.getKeyValue())); const { hashType, tagSize } = this.keyFactory.validateHmacKeyFormat(keyFormat); return { hmacKeyValue: bytesAsU8(key.getKeyValue()), hashType, tagSize }; } static register() { Registry.registerKeyManager(new AesCtrHmacAeadKeyManager()); } } AesCtrHmacAeadKeyManager.SUPPORTED_PRIMITIVE = Aead; AesCtrHmacAeadKeyManager.KEY_TYPE = 'type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey'; AesCtrHmacAeadKeyManager.VERSION = 0; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWVzX2N0cl9obWFjX2FlYWRfa2V5X21hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hZWFkL2Flc19jdHJfaG1hY19hZWFkX2tleV9tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7Ozs7Ozs7Ozs7QUFFSCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQztBQUVsRSxPQUFPLEVBQUMsbUJBQW1CLEVBQUUseUJBQXlCLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFrQixVQUFVLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBZ0IsU0FBUyxFQUFZLE1BQU0sbUJBQW1CLENBQUM7QUFDN00sT0FBTyxFQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQUMvRCxPQUFPLEtBQUssUUFBUSxNQUFNLHNCQUFzQixDQUFDO0FBRWpELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHFDQUFxQyxDQUFDO0FBQzFFLE9BQU8sS0FBSyxNQUFNLE1BQU0sa0JBQWtCLENBQUM7QUFDM0MsT0FBTyxLQUFLLFVBQVUsTUFBTSxzQkFBc0IsQ0FBQztBQUVuRCxPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFckM7O0dBRUc7QUFDSCxNQUFNLHdCQUF3QjtJQVU1QjtPQUNHO0lBQ0gsTUFBTSxDQUFDLFNBQStCO1FBQ3BDLElBQUksY0FBeUMsQ0FBQztRQUM5QyxJQUFJLFNBQVMsWUFBWSxVQUFVLEVBQUU7WUFDbkMsSUFBSTtnQkFDRixjQUFjLEdBQUcseUJBQXlCLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUM7YUFDekU7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDVixNQUFNLElBQUksaUJBQWlCLENBQ3ZCLGdFQUFnRTtvQkFDaEUsd0JBQXdCLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDeEM7WUFDRCxJQUFJLENBQUMsY0FB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LE9BQU8sRUFBQyxjQUFjLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRDs7O09BR0c7SUFDSyxlQUFlLENBQUMsR0FBNkI7UUFFbkQsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNSLE1BQU0sSUFBSSxpQkFBaUIsQ0FDdkIsZ0RBQWdELENBQUMsQ0FBQztTQUN2RDtRQUNELFVBQVUsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBSSxlQUFlLEVBQUUsQ0FBQzthQUNsQixTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDO2FBQzFCLFVBQVUsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNsRSxNQUFNLEVBQUMsUUFBUSxFQUFFLE9BQU8sRUFBQyxHQUNyQixJQUFJLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JELE9BQU8sRUFBQyxZQUFZLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUMsQ0FBQztJQUN6RSxDQUFDO0lBRUQsTUFBTSxDQUFDLFFBQVE7UUFDYixRQUFRLENBQUMsa0JBQWtCLENBQUMsSUFBSSx3QkFBd0IsRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQzs7QUF6SHVCLDRDQUFtQixHQUFHLElBQUksQ0FBQztBQUM1QyxpQ0FBUSxHQUNYLDBEQUEwRCxDQUFDO0FBQ3ZDLGdDQUFPLEdBQVcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuXG5pbXBvcnQge1NlY3VyaXR5RXhjZXB0aW9ufSBmcm9tICcuLi9leGNlcHRpb24vc2VjdXJpdHlfZXhjZXB0aW9uJztcbmltcG9ydCAqIGFzIEtleU1hbmFnZXIgZnJvbSAnLi4vaW50ZXJuYWwva2V5X21hbmFnZXInO1xuaW1wb3J0IHtQYkFlc0N0ckhtYWNBZWFkS2V5LCBQYkFlc0N0ckhtYWNBZWFkS2V5Rm9ybWF0LCBQYkFlc0N0cktleSwgUGJBZXNDdHJLZXlGb3JtYXQsIFBiQWVzQ3RyUGFyYW1zLCBQYkhhc2hUeXBlLCBQYkhtYWNLZXksIFBiSG1hY0tleUZvcm1hdCwgUGJIbWFjUGFyYW1zLCBQYktleURhdGEsIFBiTWVzc2FnZX0gZnJvbSAnLi4vaW50ZXJuYWwvcHJvdG8nO1xuaW1wb3J0IHtieXRlc0FzVTgsIGJ5dGVzTGVuZ3RofSBmcm9tICcuLi9pbnRlcm5hbC9wcm90b19zaGltcyc7XG5pbXBvcnQgKiBhcyBSZWdpc3RyeSBmcm9tICcuLi9pbnRlcm5hbC9yZWdpc3RyeSc7XG5pbXBvcnQge0NvbnN0cnVjdG9yfSBmcm9tICcuLi9pbnRlcm5hbC91dGlsJztcbmltcG9ydCB7YWVzQ3RySG1hY0Zyb21SYXdLZXlzfSBmcm9tICcuLi9zdWJ0bGUvZW5jcnlwdF90aGVuX2F1dGhlbnRpY2F0ZSc7XG5pbXBvcnQgKiBhcyBSYW5kb20gZnJvbSAnLi4vc3VidGxlL3JhbmRvbSc7XG5pbXBvcnQgKiBhcyBWYWxpZGF0b3JzIGZyb20gJy4uL3N1YnRsZS92YWxpZGF0b3JzJztcblxuaW1wb3J0IHtBZWFkfSBmcm9tICcuL2ludGVybmFsL2FlYWQnO1xuXG4vKipcbiAqIEBmaW5hbFxuICovXG5jbGFzcyBBZXNDdHJIbWFjQWVhZEtleUZhY3RvcnkgaW1wbGVtZW50cyBLZXlNYW5hZ2VyLktleUZhY3Rvcnkge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBWRVJTSU9OOiBudW1iZXIgPSAwO1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNSU5fS0VZX1NJWkU6IG51bWJlciA9IDE2O1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNSU5fSVZfU0laRTogbnVtYmVyID0gMTI7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IE1BWF9JVl9TSVpFOiBudW1iZXIgPSAxNjtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTUlOX1RBR19TSVpFOiBudW1iZXIgPSAxMDtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTUFYX1RBR19TSVpFID0gbmV3IE1hcChbXG4gICAgW1BiSGFzaFR5cGUuU0hBMSwgMjBdLCBbUGJIYXNoVHlwZS5TSEEyNTYsIDMyXSwgW1BiSGFzaFR5cGUuU0hBNTEyLCA2NF1cbiAgXSk7XG5cbiAgLyoqXG4gICAqL1xuICBuZXdLZXkoa2V5Rm9ybWF0OiBQYk1lc3NhZ2V8VWludDhBcnJheSkge1xuICAgIGxldCBrZXlGb3JtYXRQcm90bzogUGJBZXNDdHJIbWFjQWVhZEtleUZvcm1hdDtcbiAgICBpZiAoa2V5Rm9ybWF0IGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAga2V5Rm9ybWF0UHJvdG8gPSBQYkFlc0N0ckhtYWNBZWFkS2V5Rm9ybWF0LmRlc2VyaWFsaXplQmluYXJ5KGtleUZvcm1hdCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAgICdDb3VsZCBub3QgcGFyc2UgdGhlIGdpdmVuIFVpbnQ4QXJyYXkgYXMgYSBzZXJpYWxpemVkIHByb3RvIG9mICcgK1xuICAgICAgICAgICAgQWVzQ3RySG1hY0FlYWRLZXlNYW5hZ2VyLktFWV9UWVBFKTtcbiAgICAgIH1cbiAgICAgIGlmICgha2V5Rm9ybWF0UHJvdG8gfHwgIWtleUZvcm1hdFByb3RvLmdldEFlc0N0cktleUZvcm1hdCgpIHx8XG4gICAgICAgICAgIWtleUZvcm1hdFByb3RvLmdldEhtYWNLZXlGb3JtYXQoKSkge1xuICAgICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgICAnQ291bGQgbm90IHBhcnNlIHRoZSBnaXZlbiBVaW50OEFycmF5IGFzIGEgc2VyaWFsaXplZCBwcm90byBvZiAnICtcbiAgICAgICAgICAgIEFlc0N0ckhtYWNBZWFkS2V5TWFuYWdlci5LRVlfVFlQRSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChrZXlGb3JtYXQgaW5zdGFuY2VvZiBQYkFlc0N0ckhtYWNBZWFkS2V5Rm9ybWF0KSB7XG4gICAgICBrZXlGb3JtYXRQcm90byA9IGtleUZvcm1hdDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKCdFeHBlY3RlZCBBZXNDdHJIbWFjQWVhZEtleUZvcm1hdC1wcm90bycpO1xuICAgIH1cblxuICAgIGNvbnN0IHthZXNDdHJQYXJhbXMsIGFlc0N0cktleVNpemV9ID1cbiAgICAgICAgdGhpcy52YWxpZGF0ZUFlc0N0cktleUZvcm1hdChrZXlGb3JtYXRQcm90by5nZXRBZXNDdHJLZXlGb3JtYXQoKSk7XG4gICAgY29uc3QgYWVzQ3RyS2V5ID0gKG5ldyBQYkFlc0N0cktleSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuc2V0VmVyc2lvbihBZXNDdHJIbWFjQWVhZEtleUZhY3RvcnkuVkVSU0lPTilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFBhcmFtcyhhZXNDdHJQYXJhbXMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRLZXlWYWx1ZShSYW5kb20ucmFuZEJ5dGVzKGFlc0N0cktleVNpemUpKTtcbiAgICBjb25zdCB7aG1hY1BhcmFtcywgaG1hY0tleVNpemV9ID1cbiAgICAgICAgdGhpcy52YWxpZGF0ZUhtYWNLZXlGb3JtYXQoa2V5Rm9ybWF0UHJvdG8uZ2V0SG1hY0tleUZvcm1hdCgpKTtcbiAgICBjb25zdCBobWFjS2V5ID0gKG5ldyBQYkhtYWNLZXkoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRWZXJzaW9uKEFlc0N0ckhtYWNBZWFkS2V5RmFjdG9yeS5WRVJTSU9OKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNldFBhcmFtcyhobWFjUGFyYW1zKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNldEtleVZhbHVlKFJhbmRvbS5yYW5kQnl0ZXMoaG1hY0tleVNpemUpKTtcbiAgICBjb25zdCBhZXNDdHJIbWFjQWVhZEtleSA9XG4gICAgICAgIChuZXcgUGJBZXNDdHJIbWFjQWVhZEtleSgpKS5zZXRBZXNDdHJLZXkoYWVzQ3RyS2V5KS5zZXRIbWFjS2V5KGhtYWNLZXkpO1xuICAgIHJldHVybiBhZXNDdHJIbWFjQWVhZEtleTtcbiAgfVxuXG4gIC8qKlxuICAgKi9cbiAgbmV3S2V5RGF0YShzZXJpYWxpemVkS2V5Rm9ybWF0OiBVaW50OEFycmF5KSB7XG4gICAgY29uc3Qga2V5ID0gKHRoaXMubmV3S2V5KHNlcmlhbGl6ZWRLZXlGb3JtYXQpKTtcbiAgICBjb25zdCBrZXlEYXRhID1cbiAgICAgICAgKG5ldyBQYktleURhdGEoKSlcbiAgICAgICAgICAgIC5zZXRUeXBlVXJsKEFlc0N0ckhtYWNBZWFkS2V5TWFuYWdlci5LRVlfVFlQRSlcbiAgICAgICAgICAgIC5zZXRWYWx1ZShrZXkuc2VyaWFsaXplQmluYXJ5KCkpXG4gICAgICAgICAgICAuc2V0S2V5TWF0ZXJpYWxUeXBlKFBiS2V5RGF0YS5LZXlNYXRlcmlhbFR5cGUuU1lNTUVUUklDKTtcbiAgICByZXR1cm4ga2V5RGF0YTtcbiAgfVxuXG4gIC8vIGhlbHBlciBmdW5jdGlvbnNcbiAgLyoqXG4gICAqIENoZWNrcyB0aGUgcGFyYW1ldGVycyBhbmQgc2l6ZSBvZiBhIGdpdmVuIGtleUZvcm1hdC5cbiAgICpcbiAgICovXG4gIHZhbGlkYXRlQWVzQ3RyS2V5Rm9ybWF0KGtleUZvcm1hdDogdW5kZWZpbmVkfG51bGx8UGJBZXNDdHJLZXlGb3JtYXQpOlxuICAgICAge2Flc0N0clBhcmFtczogUGJBZXNDdHJQYXJhbXMsIGFlc0N0cktleVNpemU6IG51bWJlciwgaXZTaXplOiBudW1iZXJ9IHtcbiAgICBpZiAoIWtleUZvcm1hdCkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdJbnZhbGlkIEFFUyBDVFIgSE1BQyBrZXkgZm9ybWF0OiBrZXkgZm9ybWF0IHVuZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBhZXNDdHJLZXlTaXplID0ga2V5Rm9ybWF0LmdldEtleVNpemUoKTtcbiAgICBWYWxpZGF0b3JzLnZhbGlkYXRlQWVzS2V5U2l6ZShhZXNDdHJLZXlTaXplKTtcbiAgICBjb25zdCBhZXNDdHJQYXJhbXMgPSBrZXlGb3JtYXQuZ2V0UGFyYW1zKCk7XG4gICAgaWYgKCFhZXNDdHJQYXJhbXMpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW52YWxpZCBBRVMgQ1RSIEhNQUMga2V5IGZvcm1hdDogcGFyYW1zIHVuZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBpdlNpemUgPSBhZXNDdHJQYXJhbXMuZ2V0SXZTaXplKCk7XG4gICAgaWYgKGl2U2l6ZSA8IEFlc0N0ckhtYWNBZWFkS2V5RmFjdG9yeS5NSU5fSVZfU0laRSB8fFxuICAgICAgICBpdlNpemUgPiBBZXNDdHJIbWFjQWVhZEtleUZhY3RvcnkuTUFYX0lWX1NJWkUpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW52YWxpZCBBRVMgQ1RSIEhNQUMga2V5IGZvcm1hdDogSVYgc2l6ZSBpcyBvdXQgb2YgcmFuZ2U6ICcgK1xuICAgICAgICAgIGl2U2l6ZSk7XG4gICAgfVxuICAgIHJldHVybiB7YWVzQ3RyUGFyYW1zLCBhZXNDdHJLZXlTaXplLCBpdlNpemV9O1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGUgcGFyYW1ldGVycyBhbmQgc2l6ZSBvZiBhIGdpdmVuIGtleUZvcm1hdC5cbiAgICpcbiAgICovXG4gIHZhbGlkYXRlSG1hY0tleUZvcm1hdChrZXlGb3JtYXQ6IHVuZGVmaW5lZHxudWxsfFBiSG1hY0tleUZvcm1hdCk6IHtcbiAgICBobWFjUGFyYW1zOiBQYkhtYWNQYXJhbXMsXG4gICAgaG1hY0tleVNpemU6IG51bWJlcixcbiAgICBoYXNoVHlwZTogc3RyaW5nLFxuICAgIHRhZ1NpemU6IG51bWJlcixcbiAgfSB7XG4gICAgaWYgKCFrZXlGb3JtYXQpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW52YWxpZCBBRVMgQ1RSIEhNQUMga2V5IGZvcm1hdDoga2V5IGZvcm1hdCB1bmRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgaG1hY0tleVNpemUgPSBrZXlGb3JtYXQuZ2V0S2V5U2l6ZSgpO1xuICAgIGlmIChobWFjS2V5U2l6ZSA8IEFlc0N0ckhtYWNBZWFkS2V5RmFjdG9yeS5NSU5fS0VZX1NJWkUpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW52YWxpZCBBRVMgQ1RSIEhNQUMga2V5IGZvcm1hdDogSE1BQyBrZXkgaXMgdG9vIHNtYWxsOiAnICtcbiAgICAgICAgICBrZXlGb3JtYXQuZ2V0S2V5U2l6ZSgpKTtcbiAgICB9XG4gICAgY29uc3QgaG1hY1BhcmFtcyA9IGtleUZvcm1hdC5nZXRQYXJhbXMoKTtcbiAgICBpZiAoIWhtYWNQYXJhbXMpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW52YWxpZCBBRVMgQ1RSIEhNQUMga2V5IGZvcm1hdDogcGFyYW1zIHVuZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCB0YWdTaXplID0gaG1hY1BhcmFtcy5nZXRUYWdTaXplKCk7XG4gICAgaWYgKHRhZ1NpemUgPCBBZXNDdHJIbWFjQWVhZEtleUZhY3RvcnkuTUlOX1RBR19TSVpFKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ0ludmFsaWQgSE1BQyBwYXJhbXM6IHRhZyBzaXplICcgKyB0YWdTaXplICsgJyBpcyB0b28gc21hbGwuJyk7XG4gICAgfVxuICAgIGlmICghQWVzQ3RySG1hY0FlYWRLZXlGYWN0b3J5Lk1BWF9UQUdfU0laRS5oYXMoaG1hY1BhcmFtcy5nZXRIYXNoKCkpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1Vua25vd24gaGFzaCB0eXBlLicpO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIHRhZ1NpemUgPlxuICAgICAgICBBZXNDdHJIbWFjQWVhZEtleUZhY3RvcnkuTUFYX1RBR19TSVpFLmdldChobWFjUGFyYW1zLmdldEhhc2goKSkhKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ0ludmFsaWQgSE1BQyBwYXJhbXM6IHRhZyBzaXplICcgKyB0YWdTaXplICsgJyBpcyBvdXQgb2YgcmFuZ2UuJyk7XG4gICAgfVxuICAgIGxldCBoYXNoVHlwZTogc3RyaW5nO1xuICAgIHN3aXRjaCAoaG1hY1BhcmFtcy5nZXRIYXNoKCkpIHtcbiAgICAgIGNhc2UgUGJIYXNoVHlwZS5TSEExOlxuICAgICAgICBoYXNoVHlwZSA9ICdTSEEtMSc7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQYkhhc2hUeXBlLlNIQTI1NjpcbiAgICAgICAgaGFzaFR5cGUgPSAnU0hBLTI1Nic7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQYkhhc2hUeXBlLlNIQTUxMjpcbiAgICAgICAgaGFzaFR5cGUgPSAnU0hBLTUxMic7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaGFzaFR5cGUgPSAnVU5LTk9XTiBIQVNIJztcbiAgICB9XG4gICAgcmV0dXJuIHtobWFjUGFyYW1zLCBobWFjS2V5U2l6ZSwgaGFzaFR5cGUsIHRhZ1NpemV9O1xuICB9XG59XG5cbi8qKlxuICogQGZpbmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBBZXNDdHJIbWFjQWVhZEtleU1hbmFnZXIgaW1wbGVtZW50cyBLZXlNYW5hZ2VyLktleU1hbmFnZXI8QWVhZD4ge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBTVVBQT1JURURfUFJJTUlUSVZFID0gQWVhZDtcbiAgc3RhdGljIEtFWV9UWVBFOiBzdHJpbmcgPVxuICAgICAgJ3R5cGUuZ29vZ2xlYXBpcy5jb20vZ29vZ2xlLmNyeXB0by50aW5rLkFlc0N0ckhtYWNBZWFkS2V5JztcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVkVSU0lPTjogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSByZWFkb25seSBrZXlGYWN0b3J5ID0gbmV3IEFlc0N0ckhtYWNBZWFkS2V5RmFjdG9yeSgpO1xuXG4gIC8qKlxuICAgKi9cbiAgYXN5bmMgZ2V0UHJpbWl0aXZlKFxuICAgICAgcHJpbWl0aXZlVHlwZTogQ29uc3RydWN0b3I8QWVhZD4sIGtleTogUGJLZXlEYXRhfFBiTWVzc2FnZSkge1xuICAgIGlmIChwcmltaXRpdmVUeXBlICE9IHRoaXMuZ2V0UHJpbWl0aXZlVHlwZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ1JlcXVlc3RlZCBwcmltaXRpdmUgdHlwZSB3aGljaCBpcyBub3QgJyArXG4gICAgICAgICAgJ3N1cHBvcnRlZCBieSB0aGlzIGtleSBtYW5hZ2VyLicpO1xuICAgIH1cbiAgICBsZXQgZGVzZXJpYWxpemVkS2V5OiBQYkFlc0N0ckhtYWNBZWFkS2V5O1xuICAgIGlmIChrZXkgaW5zdGFuY2VvZiBQYktleURhdGEpIHtcbiAgICAgIGlmICghdGhpcy5kb2VzU3VwcG9ydChrZXkuZ2V0VHlwZVVybCgpKSkge1xuICAgICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgICAnS2V5IHR5cGUgJyArIGtleS5nZXRUeXBlVXJsKCkgK1xuICAgICAgICAgICAgJyBpcyBub3Qgc3VwcG9ydGVkLiBUaGlzIGtleSBtYW5hZ2VyIHN1cHBvcnRzICcgK1xuICAgICAgICAgICAgdGhpcy5nZXRLZXlUeXBlKCkgKyAnLicpO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgZGVzZXJpYWxpemVkS2V5ID0gUGJBZXNDdHJIbWFjQWVhZEtleS5kZXNlcmlhbGl6ZUJpbmFyeShrZXkuZ2V0VmFsdWUoKSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAgICdDb3VsZCBub3QgcGFyc2UgdGhlIGtleSBpbiBrZXkgZGF0YSBhcyBhIHNlcmlhbGl6ZWQgcHJvdG8gb2YgJyArXG4gICAgICAgICAgICBBZXNDdHJIbWFjQWVhZEtleU1hbmFnZXIuS0VZX1RZUEUpO1xuICAgICAgfVxuICAgICAgaWYgKGRlc2VyaWFsaXplZEtleSA9PT0gbnVsbCB8fCBkZXNlcmlhbGl6ZWRLZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgICAnQ291bGQgbm90IHBhcnNlIHRoZSBrZXkgaW4ga2V5IGRhdGEgYXMgYSBzZXJpYWxpemVkIHByb3RvIG9mICcgK1xuICAgICAgICAgICAgQWVzQ3RySG1hY0FlYWRLZXlNYW5hZ2VyLktFWV9UWVBFKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGtleSBpbnN0YW5jZW9mIFBiQWVzQ3RySG1hY0FlYWRLZXkpIHtcbiAgICAgIGRlc2VyaWFsaXplZEtleSA9IGtleTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdHaXZlbiBrZXkgdHlwZSBpcyBub3Qgc3VwcG9ydGVkLiAnICtcbiAgICAgICAgICAnVGhpcyBrZXkgbWFuYWdlciBzdXBwb3J0cyAnICsgdGhpcy5nZXRLZXlUeXBlKCkgKyAnLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHthZXNDdHJLZXlWYWx1ZSwgaXZTaXplfSA9XG4gICAgICAgIHRoaXMudmFsaWRhdGVBZXNDdHJLZXkoZGVzZXJpYWxpemVkS2V5LmdldEFlc0N0cktleSgpKTtcbiAgICBjb25zdCB7aG1hY0tleVZhbHVlLCBoYXNoVHlwZSwgdGFnU2l6ZX0gPVxuICAgICAgICB0aGlzLnZhbGlkYXRlSG1hY0tleShkZXNlcmlhbGl6ZWRLZXkuZ2V0SG1hY0tleSgpKTtcbiAgICByZXR1cm4gYXdhaXQgYWVzQ3RySG1hY0Zyb21SYXdLZXlzKFxuICAgICAgICBhZXNDdHJLZXlWYWx1ZSwgaXZTaXplLCBoYXNoVHlwZSwgaG1hY0tleVZhbHVlLCB0YWdTaXplKTtcbiAgfVxuXG4gIC8qKlxuICAgKi9cbiAgZG9lc1N1cHBvcnQoa2V5VHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGtleVR5cGUgPT09IHRoaXMuZ2V0S2V5VHlwZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqL1xuICBnZXRLZXlUeXBlKCkge1xuICAgIHJldHVybiBBZXNDdHJIbWFjQWVhZEtleU1hbmFnZXIuS0VZX1RZUEU7XG4gIH1cblxuICAvKipcbiAgICovXG4gIGdldFByaW1pdGl2ZVR5cGUoKSB7XG4gICAgcmV0dXJuIEFlc0N0ckhtYWNBZWFkS2V5TWFuYWdlci5TVVBQT1JURURfUFJJTUlUSVZFO1xuICB9XG5cbiAgLyoqXG4gICAqL1xuICBnZXRWZXJzaW9uKCkge1xuICAgIHJldHVybiBBZXNDdHJIbWFjQWVhZEtleU1hbmFnZXIuVkVSU0lPTjtcbiAgfVxuXG4gIC8qKlxuICAgKi9cbiAgZ2V0S2V5RmFjdG9yeSgpIHtcbiAgICByZXR1cm4gdGhpcy5rZXlGYWN0b3J5O1xuICB9XG5cbiAgLy8gaGVscGVyIGZ1bmN0aW9uc1xuICAvKipcbiAgICogQ2hlY2tzIHRoZSBwYXJhbWV0ZXJzIGFuZCBzaXplIG9mIGEgZ2l2ZW4gQUVTLUNUUiBrZXkuXG4gICAqXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlQWVzQ3RyS2V5KGtleTogdW5kZWZpbmVkfG51bGx8UGJBZXNDdHJLZXkpOlxuICAgICAge2Flc0N0cktleVZhbHVlOiBVaW50OEFycmF5LCBpdlNpemU6IG51bWJlcn0ge1xuICAgIGlmICgha2V5KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ0ludmFsaWQgQUVTIENUUiBITUFDIGtleSBmb3JtYXQ6IGtleSB1bmRlZmluZWQnKTtcbiAgICB9XG4gICAgVmFsaWRhdG9ycy52YWxpZGF0ZVZlcnNpb24oa2V5LmdldFZlcnNpb24oKSwgdGhpcy5nZXRWZXJzaW9uKCkpO1xuICAgIGNvbnN0IGtleUZvcm1hdCA9IChuZXcgUGJBZXNDdHJLZXlGb3JtYXQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFBhcmFtcyhrZXkuZ2V0UGFyYW1zKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRLZXlTaXplKGJ5dGVzTGVuZ3RoKGtleS5nZXRLZXlWYWx1ZSgpKSk7XG4gICAgY29uc3Qge2l2U2l6ZX0gPSB0aGlzLmtleUZhY3RvcnkudmFsaWRhdGVBZXNDdHJLZXlGb3JtYXQoa2V5Rm9ybWF0KTtcbiAgICByZXR1cm4ge2Flc0N0cktleVZhbHVlOiBieXRlc0FzVTgoa2V5LmdldEtleVZhbHVlKCkpLCBpdlNpemV9O1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGUgcGFyYW1ldGVycyBhbmQgc2l6ZSBvZiBhIGdpdmVuIEhNQUMga2V5LlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUhtYWNLZXkoa2V5OiB1bmRlZmluZWR8bnVsbHxQYkhtYWNLZXkpOlxuICAgICAge2htYWNLZXlWYWx1ZTogVWludDhBcnJheSwgaGFzaFR5cGU6IHN0cmluZywgdGFnU2l6ZTogbnVtYmVyfSB7XG4gICAgaWYgKCFrZXkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnSW52YWxpZCBBRVMgQ1RSIEhNQUMga2V5IGZvcm1hdDoga2V5IHVuZGVmaW5lZCcpO1xuICAgIH1cbiAgICBWYWxpZGF0b3JzLnZhbGlkYXRlVmVyc2lvbihrZXkuZ2V0VmVyc2lvbigpLCB0aGlzLmdldFZlcnNpb24oKSk7XG4gICAgY29uc3Qga2V5Rm9ybWF0ID0gKG5ldyBQYkhtYWNLZXlGb3JtYXQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFBhcmFtcyhrZXkuZ2V0UGFyYW1zKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRLZXlTaXplKGJ5dGVzTGVuZ3RoKGtleS5nZXRLZXlWYWx1ZSgpKSk7XG4gICAgY29uc3Qge2hhc2hUeXBlLCB0YWdTaXplfSA9XG4gICAgICAgIHRoaXMua2V5RmFjdG9yeS52YWxpZGF0ZUhtYWNLZXlGb3JtYXQoa2V5Rm9ybWF0KTtcbiAgICByZXR1cm4ge2htYWNLZXlWYWx1ZTogYnl0ZXNBc1U4KGtleS5nZXRLZXlWYWx1ZSgpKSwgaGFzaFR5cGUsIHRhZ1NpemV9O1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyKCkge1xuICAgIFJlZ2lzdHJ5LnJlZ2lzdGVyS2V5TWFuYWdlcihuZXcgQWVzQ3RySG1hY0FlYWRLZXlNYW5hZ2VyKCkpO1xuICB9XG59XG4iXX0=