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.

215 lines 28.1 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 { PbEcdsaKeyFormat, PbEcdsaPrivateKey, PbEcdsaPublicKey, PbKeyData } from '../internal/proto'; import * as Util from '../internal/util'; import * as Bytes from '../subtle/bytes'; import * as ecdsaSign from '../subtle/ecdsa_sign'; import * as EllipticCurves from '../subtle/elliptic_curves'; import { EcdsaPublicKeyManager } from './ecdsa_public_key_manager'; import * as EcdsaUtil from './ecdsa_util'; import { PublicKeySign } from './internal/public_key_sign'; const VERSION = 0; /** * @final */ class EcdsaPrivateKeyFactory { /** */ newKey(keyFormat) { return __awaiter(this, void 0, void 0, function* () { if (!keyFormat) { throw new SecurityException('Key format has to be non-null.'); } const keyFormatProto = EcdsaPrivateKeyFactory.getKeyFormatProto(keyFormat); EcdsaUtil.validateKeyFormat(keyFormatProto); const params = keyFormatProto.getParams(); if (!params) { throw new SecurityException('Params not set'); } const curveTypeProto = params.getCurve(); const curveTypeSubtle = Util.curveTypeProtoToSubtle(curveTypeProto); const curveName = EllipticCurves.curveToString(curveTypeSubtle); const keyPair = yield EllipticCurves.generateKeyPair('ECDSA', curveName); const jsonPublicKey = yield EllipticCurves.exportCryptoKey(keyPair.publicKey); const jsonPrivateKey = yield EllipticCurves.exportCryptoKey(keyPair.privateKey); return EcdsaPrivateKeyFactory.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(EcdsaPrivateKeyManager.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(EcdsaPublicKeyManager.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 PbEcdsaPublicKey()) .setVersion(EcdsaPublicKeyManager.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 PbEcdsaPrivateKey()) .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 EcdsaKeyFormat-proto (otherwise). * */ static getKeyFormatProto(keyFormat) { if (keyFormat instanceof Uint8Array) { return EcdsaPrivateKeyFactory.deserializeKeyFormat(keyFormat); } else if (keyFormat instanceof PbEcdsaKeyFormat) { return keyFormat; } else { throw new SecurityException('Expected ' + EcdsaPrivateKeyManager.KEY_TYPE + ' key format proto.'); } } static deserializeKeyFormat(keyFormat) { let keyFormatProto; try { keyFormatProto = PbEcdsaKeyFormat.deserializeBinary(keyFormat); } catch (e) { throw new SecurityException('Input cannot be parsed as ' + EcdsaPrivateKeyManager.KEY_TYPE + ' key format proto.'); } if (!keyFormatProto.getParams()) { throw new SecurityException('Input cannot be parsed as ' + EcdsaPrivateKeyManager.KEY_TYPE + ' key format proto.'); } return keyFormatProto; } } /** * @final */ export class EcdsaPrivateKeyManager { constructor() { this.keyFactory = new EcdsaPrivateKeyFactory(); } 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 = EcdsaPrivateKeyManager.getKeyProto(key); EcdsaUtil.validatePrivateKey(keyProto, VERSION, EcdsaPublicKeyManager.VERSION); const recepientPrivateKey = EcdsaUtil.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 hash = Util.hashTypeProtoToString(params.getHashType()); const encoding = EcdsaUtil.encodingTypeProtoToEnum(params.getEncoding()); return ecdsaSign.fromJsonWebKey(recepientPrivateKey, hash, encoding); }); } doesSupport(keyType) { return keyType === this.getKeyType(); } getKeyType() { return EcdsaPrivateKeyManager.KEY_TYPE; } getPrimitiveType() { return EcdsaPrivateKeyManager.SUPPORTED_PRIMITIVE; } getVersion() { return VERSION; } getKeyFactory() { return this.keyFactory; } static getKeyProto(keyMaterial) { if (keyMaterial instanceof PbKeyData) { return EcdsaPrivateKeyManager.getKeyProtoFromKeyData(keyMaterial); } if (keyMaterial instanceof PbEcdsaPrivateKey) { return keyMaterial; } throw new SecurityException('Key type is not supported. This key ' + 'manager supports ' + EcdsaPrivateKeyManager.KEY_TYPE + '.'); } static getKeyProtoFromKeyData(keyData) { if (keyData.getTypeUrl() !== EcdsaPrivateKeyManager.KEY_TYPE) { throw new SecurityException('Key type ' + keyData.getTypeUrl() + ' is not supported. This key manager supports ' + EcdsaPrivateKeyManager.KEY_TYPE + '.'); } return deserializePrivateKey(keyData.getValue()); } } EcdsaPrivateKeyManager.SUPPORTED_PRIMITIVE = PublicKeySign; EcdsaPrivateKeyManager.KEY_TYPE = 'type.googleapis.com/google.crypto.tink.EcdsaPrivateKey'; function deserializePrivateKey(serializedPrivateKey) { let key; try { key = PbEcdsaPrivateKey.deserializeBinary(serializedPrivateKey); } catch (e) { throw new SecurityException('Input cannot be parsed as ' + EcdsaPrivateKeyManager.KEY_TYPE + ' key-proto.'); } if (!key.getPublicKey() || !key.getKeyValue()) { throw new SecurityException('Input cannot be parsed as ' + EcdsaPrivateKeyManager.KEY_TYPE + ' key-proto.'); } return key; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNkc2FfcHJpdmF0ZV9rZXlfbWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NpZ25hdHVyZS9lY2RzYV9wcml2YXRlX2tleV9tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7Ozs7Ozs7Ozs7QUFFSCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQztBQUVsRSxPQUFPLEVBQUMsZ0JBQWdCLEVBQWlCLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLFNBQVMsRUFBWSxNQUFNLG1CQUFtQixDQUFDO0FBRTdILE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFFekMsT0FBTyxLQUFLLEtBQUssTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEtBQUssU0FBUyxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sS0FBSyxjQUFjLE1BQU0sMkJBQTJCLENBQUM7QUFFNUQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDakUsT0FBTyxLQUFLLFNBQVMsTUFBTSxjQUFjLENBQUM7QUFDMUMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBRXpELE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQztBQUVsQjs7R0FFRztBQUNILE1BQU0sc0JBQXNCO0lBQzFCO09BQ0c7SUFDRyxNQUFNLENBQUMsU0FBK0I7O1lBQzFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ2QsTUFBTSxJQUFJLGlCQUFpQixDQUFDLGdDQUFnQyxDQUFDLENBQUM7YUFDL0Q7WUFDRCxNQUFNLGNBQWMsR0FBRyxzQkFBc0IsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMzRSxTQUFTLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUMsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzFD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bkQsQ0FBQzs7QUF0RXVCLDBDQUFtQixHQUFHLGFBQWEsQ0FBQztBQUNyRCwrQkFBUSxHQUNYLHdEQUF3RCxDQUFDO0FBdUUvRCxTQUFTLHFCQUFxQixDQUFDLG9CQUFnQztJQUU3RCxJQUFJLEdBQXNCLENBQUM7SUFDM0IsSUFBSTtRQUNGLEdBQUcsR0FBRyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0tBQ2pFO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDVixNQUFNLElBQUksaUJBQWlCLENBQ3ZCLDRCQUE0QixHQUFHLHNCQUFzQixDQUFDLFFBQVE7WUFDOUQsYUFBYSxDQUFDLENBQUM7S0FDcEI7SUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFO1FBQzdDLE1BQU0sSUFBSSxpQkFBaUIsQ0FDdkIsNEJBQTRCLEdBQUcsc0JBQXNCLENBQUMsUUFBUTtZQUM5RCxhQUFhLENBQUMsQ0FBQztLQUNwQjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHtTZWN1cml0eUV4Y2VwdGlvbn0gZnJvbSAnLi4vZXhjZXB0aW9uL3NlY3VyaXR5X2V4Y2VwdGlvbic7XG5pbXBvcnQgKiBhcyBLZXlNYW5hZ2VyIGZyb20gJy4uL2ludGVybmFsL2tleV9tYW5hZ2VyJztcbmltcG9ydCB7UGJFY2RzYUtleUZvcm1hdCwgUGJFY2RzYVBhcmFtcywgUGJFY2RzYVByaXZhdGVLZXksIFBiRWNkc2FQdWJsaWNLZXksIFBiS2V5RGF0YSwgUGJNZXNzYWdlfSBmcm9tICcuLi9pbnRlcm5hbC9wcm90byc7XG5pbXBvcnQge1Byb3RvQnl0ZXN9IGZyb20gJy4uL2ludGVybmFsL3Byb3RvX3NoaW1zJztcbmltcG9ydCAqIGFzIFV0aWwgZnJvbSAnLi4vaW50ZXJuYWwvdXRpbCc7XG5pbXBvcnQge0NvbnN0cnVjdG9yfSBmcm9tICcuLi9pbnRlcm5hbC91dGlsJztcbmltcG9ydCAqIGFzIEJ5dGVzIGZyb20gJy4uL3N1YnRsZS9ieXRlcyc7XG5pbXBvcnQgKiBhcyBlY2RzYVNpZ24gZnJvbSAnLi4vc3VidGxlL2VjZHNhX3NpZ24nO1xuaW1wb3J0ICogYXMgRWxsaXB0aWNDdXJ2ZXMgZnJvbSAnLi4vc3VidGxlL2VsbGlwdGljX2N1cnZlcyc7XG5cbmltcG9ydCB7RWNkc2FQdWJsaWNLZXlNYW5hZ2VyfSBmcm9tICcuL2VjZHNhX3B1YmxpY19rZXlfbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBFY2RzYVV0aWwgZnJvbSAnLi9lY2RzYV91dGlsJztcbmltcG9ydCB7UHVibGljS2V5U2lnbn0gZnJvbSAnLi9pbnRlcm5hbC9wdWJsaWNfa2V5X3NpZ24nO1xuXG5jb25zdCBWRVJTSU9OID0gMDtcblxuLyoqXG4gKiBAZmluYWxcbiAqL1xuY2xhc3MgRWNkc2FQcml2YXRlS2V5RmFjdG9yeSBpbXBsZW1lbnRzIEtleU1hbmFnZXIuUHJpdmF0ZUtleUZhY3Rvcnkge1xuICAvKipcbiAgICovXG4gIGFzeW5jIG5ld0tleShrZXlGb3JtYXQ6IFBiTWVzc2FnZXxVaW50OEFycmF5KTogUHJvbWlzZTxQYkVjZHNhUHJpdmF0ZUtleT4ge1xuICAgIGlmICgha2V5Rm9ybWF0KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0tleSBmb3JtYXQgaGFzIHRvIGJlIG5vbi1udWxsLicpO1xuICAgIH1cbiAgICBjb25zdCBrZXlGb3JtYXRQcm90byA9IEVjZHNhUHJpdmF0ZUtleUZhY3RvcnkuZ2V0S2V5Rm9ybWF0UHJvdG8oa2V5Rm9ybWF0KTtcbiAgICBFY2RzYVV0aWwudmFsaWRhdGVLZXlGb3JtYXQoa2V5Rm9ybWF0UHJvdG8pO1xuICAgIGNvbnN0IHBhcmFtcyA9IGtleUZvcm1hdFByb3RvLmdldFBhcmFtcygpO1xuICAgIGlmICghcGFyYW1zKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1BhcmFtcyBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGN1cnZlVHlwZVByb3RvID0gcGFyYW1zLmdldEN1cnZlKCk7XG4gICAgY29uc3QgY3VydmVUeXBlU3VidGxlID0gVXRpbC5jdXJ2ZVR5cGVQcm90b1RvU3VidGxlKGN1cnZlVHlwZVByb3RvKTtcbiAgICBjb25zdCBjdXJ2ZU5hbWUgPSBFbGxpcHRpY0N1cnZlcy5jdXJ2ZVRvU3RyaW5nKGN1cnZlVHlwZVN1YnRsZSk7XG4gICAgY29uc3Qga2V5UGFpciA9IGF3YWl0IEVsbGlwdGljQ3VydmVzLmdlbmVyYXRlS2V5UGFpcignRUNEU0EnLCBjdXJ2ZU5hbWUpO1xuICAgIGNvbnN0IGpzb25QdWJsaWNLZXkgPVxuICAgICAgICBhd2FpdCBFbGxpcHRpY0N1cnZlcy5leHBvcnRDcnlwdG9LZXkoa2V5UGFpci5wdWJsaWNLZXkhKTtcbiAgICBjb25zdCBqc29uUHJpdmF0ZUtleSA9XG4gICAgICAgIGF3YWl0IEVsbGlwdGljQ3VydmVzLmV4cG9ydENyeXB0b0tleShrZXlQYWlyLnByaXZhdGVLZXkhKTtcbiAgICByZXR1cm4gRWNkc2FQcml2YXRlS2V5RmFjdG9yeS5qc29uVG9Qcm90b0tleShcbiAgICAgICAganNvblByaXZhdGVLZXksIGpzb25QdWJsaWNLZXksIHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICovXG4gIGFzeW5jIG5ld0tleURhdGEoc2VyaWFsaXplZEtleUZvcm1hdDogVWludDhBcnJheSk6IFByb21pc2U8UGJLZXlEYXRhPiB7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5uZXdLZXkoc2VyaWFsaXplZEtleUZvcm1hdCk7XG4gICAgY29uc3Qga2V5RGF0YSA9XG4gICAgICAgIChuZXcgUGJLZXlEYXRhKCkpXG4gICAgICAgICAgICAuc2V0VHlwZVVybChFY2RzYVByaXZhdGVLZXlNYW5hZ2VyLktFWV9UWVBFKVxuICAgICAgICAgICAgLnNldFZhbHVlKGtleS5zZXJpYWxpemVCaW5hcnkoKSlcbiAgICAgICAgICAgIC5zZXRLZXlNYXRlcmlhbFR5cGUoUGJLZXlEYXRhLktleU1hdGVyaWFsVHlwZS5BU1lNTUVUUklDX1BSSVZBVEUpO1xuICAgIHJldHVybiBrZXlEYXRhO1xuICB9XG5cbiAgZ2V0UHVibGljS2V5RGF0YShzZXJpYWxpemVkUHJpdmF0ZUtleTogVWludDhBcnJheSkge1xuICAgIGNvbnN0IHByaXZhdGVLZXkgPSBkZXNlcmlhbGl6ZVByaXZhdGVLZXkoc2VyaWFsaXplZFByaXZhdGVLZXkpO1xuICAgIGNvbnN0IHB1YmxpY0tleSA9IHByaXZhdGVLZXkuZ2V0UHVibGljS2V5KCk7XG4gICAgaWYgKCFwdWJsaWNLZXkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignUHVibGljIGtleSBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IHB1YmxpY0tleURhdGEgPVxuICAgICAgICAobmV3IFBiS2V5RGF0YSgpKVxuICAgICAgICAgICAgLnNldFZhbHVlKHB1YmxpY0tleS5zZXJpYWxpemVCaW5hcnkoKSlcbiAgICAgICAgICAgIC5zZXRUeXBlVXJsKEVjZHNhUHVibGljS2V5TWFuYWdlci5LRVlfVFlQRSlcbiAgICAgICAgICAgIC5zZXRLZXlNYXRlcmlhbFR5cGUoUGJLZXlEYXRhLktleU1hdGVyaWFsVHlwZS5BU1lNTUVUUklDX1BVQkxJQyk7XG4gICAgcmV0dXJuIHB1YmxpY0tleURhdGE7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHByaXZhdGUga2V5IHByb3RvIGNvcnJlc3BvbmRpbmcgdG8gZ2l2ZW4gSlNPTiBrZXkgcGFpciBhbmQgd2l0aFxuICAgKiB0aGUgZ2l2ZW4gcGFyYW1zLlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMganNvblRvUHJvdG9LZXkoXG4gICAgICBqc29uUHJpdmF0ZUtleTogSnNvbldlYktleSwganNvblB1YmxpY0tleTogSnNvbldlYktleSxcbiAgICAgIHBhcmFtczogUGJFY2RzYVBhcmFtcyk6IFBiRWNkc2FQcml2YXRlS2V5IHtcbiAgICBjb25zdCB7eCwgeX0gPSBqc29uUHVibGljS2V5O1xuICAgIGlmICh4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbigneCBtdXN0IGJlIHNldCcpO1xuICAgIH1cbiAgICBpZiAoeSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ3kgbXVzdCBiZSBzZXQnKTtcbiAgICB9XG4gICAgY29uc3QgcHVibGljS2V5UHJvdG8gPSAobmV3IFBiRWNkc2FQdWJsaWNLZXkoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2V0VmVyc2lvbihFY2RzYVB1YmxpY0tleU1hbmFnZXIuVkVSU0lPTilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2V0UGFyYW1zKHBhcmFtcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2V0WChCeXRlcy5mcm9tQmFzZTY0KHgsIHRydWUpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRZKEJ5dGVzLmZyb21CYXNlNjQoeSwgdHJ1ZSkpO1xuICAgIGNvbnN0IHtkfSA9IGpzb25Qcml2YXRlS2V5O1xuICAgIGlmIChkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignZCBtdXN0IGJlIHNldCcpO1xuICAgIH1cbiAgICBjb25zdCBwcml2YXRlS2V5UHJvdG8gPSAobmV3IFBiRWNkc2FQcml2YXRlS2V5KCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRWZXJzaW9uKFZFUlNJT04pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRQdWJsaWNLZXkocHVibGljS2V5UHJvdG8pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRLZXlWYWx1ZShCeXRlcy5mcm9tQmFzZTY0KGQsIHRydWUpKTtcbiAgICByZXR1cm4gcHJpdmF0ZUtleVByb3RvO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnB1dCBrZXlGb3JtYXQgaXMgZWl0aGVyIGRlc2VyaWFsaXplZCAoaW4gY2FzZSB0aGF0IHRoZSBpbnB1dCBpc1xuICAgKiBVaW50OEFycmF5KSBvciBjaGVja2VkIHRvIGJlIGFuIEVjZHNhS2V5Rm9ybWF0LXByb3RvIChvdGhlcndpc2UpLlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0S2V5Rm9ybWF0UHJvdG8oa2V5Rm9ybWF0OiBQYk1lc3NhZ2V8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVpbnQ4QXJyYXkpOiBQYkVjZHNhS2V5Rm9ybWF0IHtcbiAgICBpZiAoa2V5Rm9ybWF0IGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgcmV0dXJuIEVjZHNhUHJpdmF0ZUtleUZhY3RvcnkuZGVzZXJpYWxpemVLZXlGb3JtYXQoa2V5Rm9ybWF0KTtcbiAgICB9IGVsc2UgaWYgKGtleUZvcm1hdCBpbnN0YW5jZW9mIFBiRWNkc2FLZXlGb3JtYXQpIHtcbiAgICAgIHJldHVybiBrZXlGb3JtYXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnRXhwZWN0ZWQgJyArIEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUgKyAnIGtleSBmb3JtYXQgcHJvdG8uJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZGVzZXJpYWxpemVLZXlGb3JtYXQoa2V5Rm9ybWF0OiBVaW50OEFycmF5KTogUGJFY2RzYUtleUZvcm1hdCB7XG4gICAgbGV0IGtleUZvcm1hdFByb3RvOiBQYkVjZHNhS2V5Rm9ybWF0O1xuICAgIHRyeSB7XG4gICAgICBrZXlGb3JtYXRQcm90byA9IFBiRWNkc2FLZXlGb3JtYXQuZGVzZXJpYWxpemVCaW5hcnkoa2V5Rm9ybWF0KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUgK1xuICAgICAgICAgICcga2V5IGZvcm1hdCBwcm90by4nKTtcbiAgICB9XG4gICAgaWYgKCFrZXlGb3JtYXRQcm90by5nZXRQYXJhbXMoKSkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdJbnB1dCBjYW5ub3QgYmUgcGFyc2VkIGFzICcgKyBFY2RzYVByaXZhdGVLZXlNYW5hZ2VyLktFWV9UWVBFICtcbiAgICAgICAgICAnIGtleSBmb3JtYXQgcHJvdG8uJyk7XG4gICAgfVxuICAgIHJldHVybiBrZXlGb3JtYXRQcm90bztcbiAgfVxufVxuXG4vKipcbiAqIEBmaW5hbFxuICovXG5leHBvcnQgY2xhc3MgRWNkc2FQcml2YXRlS2V5TWFuYWdlciBpbXBsZW1lbnRzXG4gICAgS2V5TWFuYWdlci5LZXlNYW5hZ2VyPFB1YmxpY0tleVNpZ24+IHtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgU1VQUE9SVEVEX1BSSU1JVElWRSA9IFB1YmxpY0tleVNpZ247XG4gIHN0YXRpYyBLRVlfVFlQRTogc3RyaW5nID1cbiAgICAgICd0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5FY2RzYVByaXZhdGVLZXknO1xuICBrZXlGYWN0b3J5ID0gbmV3IEVjZHNhUHJpdmF0ZUtleUZhY3RvcnkoKTtcblxuICBhc3luYyBnZXRQcmltaXRpdmUoXG4gICAgICBwcmltaXRpdmVUeXBlOiBDb25zdHJ1Y3RvcjxQdWJsaWNLZXlTaWduPiwga2V5OiBQYktleURhdGF8UGJNZXNzYWdlKSB7XG4gICAgaWYgKHByaW1pdGl2ZVR5cGUgIT09IHRoaXMuZ2V0UHJpbWl0aXZlVHlwZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oXG4gICAgICAgICAgJ1JlcXVlc3RlZCBwcmltaXRpdmUgdHlwZSB3aGljaCBpcyBub3QgJyArXG4gICAgICAgICAgJ3N1cHBvcnRlZCBieSB0aGlzIGtleSBtYW5hZ2VyLicpO1xuICAgIH1cbiAgICBjb25zdCBrZXlQcm90byA9IEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuZ2V0S2V5UHJvdG8oa2V5KTtcbiAgICBFY2RzYVV0aWwudmFsaWRhdGVQcml2YXRlS2V5KFxuICAgICAgICBrZXlQcm90bywgVkVSU0lPTiwgRWNkc2FQdWJsaWNLZXlNYW5hZ2VyLlZFUlNJT04pO1xuICAgIGNvbnN0IHJlY2VwaWVudFByaXZhdGVLZXkgPSBFY2RzYVV0aWwuZ2V0SnNvbldlYktleUZyb21Qcm90byhrZXlQcm90byk7XG4gICAgY29uc3QgcHVibGljS2V5ID0ga2V5UHJvdG8uZ2V0UHVibGljS2V5KCk7XG4gICAgaWYgKCFwdWJsaWNLZXkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignUHVibGljIGtleSBub3Qgc2V0Jyk7XG4gICAgfVxuICAgIGNvbnN0IHBhcmFtcyA9IHB1YmxpY0tleS5nZXRQYXJhbXMoKTtcbiAgICBpZiAoIXBhcmFtcykge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKCdQYXJhbXMgbm90IHNldCcpO1xuICAgIH1cbiAgICBjb25zdCBoYXNoID0gVXRpbC5oYXNoVHlwZVByb3RvVG9TdHJpbmcocGFyYW1zLmdldEhhc2hUeXBlKCkpO1xuICAgIGNvbnN0IGVuY29kaW5nID0gRWNkc2FVdGlsLmVuY29kaW5nVHlwZVByb3RvVG9FbnVtKHBhcmFtcy5nZXRFbmNvZGluZygpKTtcbiAgICByZXR1cm4gZWNkc2FTaWduLmZyb21Kc29uV2ViS2V5KHJlY2VwaWVudFByaXZhdGVLZXksIGhhc2gsIGVuY29kaW5nKTtcbiAgfVxuXG4gIGRvZXNTdXBwb3J0KGtleVR5cGU6IHN0cmluZykge1xuICAgIHJldHVybiBrZXlUeXBlID09PSB0aGlzLmdldEtleVR5cGUoKTtcbiAgfVxuXG4gIGdldEtleVR5cGUoKSB7XG4gICAgcmV0dXJuIEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEU7XG4gIH1cblxuICBnZXRQcmltaXRpdmVUeXBlKCkge1xuICAgIHJldHVybiBFY2RzYVByaXZhdGVLZXlNYW5hZ2VyLlNVUFBPUlRFRF9QUklNSVRJVkU7XG4gIH1cblxuICBnZXRWZXJzaW9uKCkge1xuICAgIHJldHVybiBWRVJTSU9OO1xuICB9XG5cbiAgZ2V0S2V5RmFjdG9yeSgpIHtcbiAgICByZXR1cm4gdGhpcy5rZXlGYWN0b3J5O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0S2V5UHJvdG8oa2V5TWF0ZXJpYWw6IFBiS2V5RGF0YXxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGJNZXNzYWdlKTogUGJFY2RzYVByaXZhdGVLZXkge1xuICAgIGlmIChrZXlNYXRlcmlhbCBpbnN0YW5jZW9mIFBiS2V5RGF0YSkge1xuICAgICAgcmV0dXJuIEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuZ2V0S2V5UHJvdG9Gcm9tS2V5RGF0YShrZXlNYXRlcmlhbCk7XG4gICAgfVxuICAgIGlmIChrZXlNYXRlcmlhbCBpbnN0YW5jZW9mIFBiRWNkc2FQcml2YXRlS2V5KSB7XG4gICAgICByZXR1cm4ga2V5TWF0ZXJpYWw7XG4gICAgfVxuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgJ0tleSB0eXBlIGlzIG5vdCBzdXBwb3J0ZWQuIFRoaXMga2V5ICcgK1xuICAgICAgICAnbWFuYWdlciBzdXBwb3J0cyAnICsgRWNkc2FQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArICcuJyk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXRLZXlQcm90b0Zyb21LZXlEYXRhKGtleURhdGE6IFBiS2V5RGF0YSk6IFBiRWNkc2FQcml2YXRlS2V5IHtcbiAgICBpZiAoa2V5RGF0YS5nZXRUeXBlVXJsKCkgIT09IEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgICAnS2V5IHR5cGUgJyArIGtleURhdGEuZ2V0VHlwZVVybCgpICtcbiAgICAgICAgICAnIGlzIG5vdCBzdXBwb3J0ZWQuIFRoaXMga2V5IG1hbmFnZXIgc3VwcG9ydHMgJyArXG4gICAgICAgICAgRWNkc2FQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArICcuJyk7XG4gICAgfVxuICAgIHJldHVybiBkZXNlcmlhbGl6ZVByaXZhdGVLZXkoa2V5RGF0YS5nZXRWYWx1ZSgpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkZXNlcmlhbGl6ZVByaXZhdGVLZXkoc2VyaWFsaXplZFByaXZhdGVLZXk6IFByb3RvQnl0ZXMpOlxuICAgIFBiRWNkc2FQcml2YXRlS2V5IHtcbiAgbGV0IGtleTogUGJFY2RzYVByaXZhdGVLZXk7XG4gIHRyeSB7XG4gICAga2V5ID0gUGJFY2RzYVByaXZhdGVLZXkuZGVzZXJpYWxpemVCaW5hcnkoc2VyaWFsaXplZFByaXZhdGVLZXkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAnSW5wdXQgY2Fubm90IGJlIHBhcnNlZCBhcyAnICsgRWNkc2FQcml2YXRlS2V5TWFuYWdlci5LRVlfVFlQRSArXG4gICAgICAgICcga2V5LXByb3RvLicpO1xuICB9XG4gIGlmICgha2V5LmdldFB1YmxpY0tleSgpIHx8ICFrZXkuZ2V0S2V5VmFsdWUoKSkge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihcbiAgICAgICAgJ0lucHV0IGNhbm5vdCBiZSBwYXJzZWQgYXMgJyArIEVjZHNhUHJpdmF0ZUtleU1hbmFnZXIuS0VZX1RZUEUgK1xuICAgICAgICAnIGtleS1wcm90by4nKTtcbiAgfVxuICByZXR1cm4ga2V5O1xufVxuIl19