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.

169 lines 16.7 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { SecurityException } from '../exception/security_exception'; import { CryptoFormat } from './crypto_format'; import { PbKeyStatusType } from './proto'; /** * Auxiliary class for PrimitiveSet * Entry-objects hold individual instances of primitives in the set. * * @template P * @final */ export class Entry { constructor(primitive, identifier, keyStatus, outputPrefixType) { this.primitive = primitive; this.identifier = identifier; this.keyStatus = keyStatus; this.outputPrefixType = outputPrefixType; } getPrimitive() { return this.primitive; } getIdentifier() { return this.identifier; } getKeyStatus() { return this.keyStatus; } getOutputPrefixType() { return this.outputPrefixType; } } /** * A container class for a set of primitives (i.e. implementations of * cryptographic primitives offered by Tink). It provides also additional * properties for the primitives it holds. In particular, one of the primitives * in the set can be distinguished as "the primary" one. * * PrimitiveSet is an auxiliary class used for supporting key rotation: * primitives in a set correspond to keys in a keyset. Users will usually work * with primitive instances which essentially wrap primitive sets. For example * an instance of an Aead-primitive for a given keyset holds a set of * Aead-primitives corresponding to the keys in the keyset, and uses the set * members to do the actual crypto operations: to encrypt data the primary * Aead-primitive from the set is used, and upon decryption the ciphertext's * prefix determines the identifier of the primitive from the set. * * PrimitiveSet is a public class to allow its use in implementations of custom * primitives. * * @final */ export class PrimitiveSet { constructor(primitiveType) { this.primitiveType = primitiveType; this.primary = null; this.identifierToPrimitivesMap = new Map(); } /** * Returns the type of primitives contained in this set. * */ getPrimitiveType() { return this.primitiveType; } /** * Creates an entry in the primitive table and returns it. * * */ addPrimitive(primitive, key) { if (!primitive) { throw new SecurityException('Primitive has to be non null.'); } if (!key) { throw new SecurityException('Key has to be non null.'); } const identifier = CryptoFormat.getOutputPrefix(key); const entry = new Entry(primitive, identifier, key.getStatus(), key.getOutputPrefixType()); this.addPrimitiveToMap(entry); return entry; } /** * Returns the entry with the primary primitive. * */ getPrimary() { return this.primary; } /** * Sets given Entry as the primary one. * */ setPrimary(primitive) { if (!primitive) { throw new SecurityException('Primary cannot be set to null.'); } if (primitive.getKeyStatus() != PbKeyStatusType.ENABLED) { throw new SecurityException('Primary has to be enabled.'); } // There has to be exactly one key enabled with this identifier. const entries = this.getPrimitives(primitive.getIdentifier()); let entryFound = false; const entriesLength = entries.length; for (let i = 0; i < entriesLength; i++) { if (entries[i].getKeyStatus() === PbKeyStatusType.ENABLED) { entryFound = true; break; } } if (!entryFound) { throw new SecurityException('Primary cannot be set to an entry which is ' + 'not held by this primitive set.'); } this.primary = primitive; } /** * Returns all primitives using RAW prefix. * */ getRawPrimitives() { return this.getPrimitives(CryptoFormat.RAW_PREFIX); } /** * Returns the entries with primitive identified with identifier. * * */ getPrimitives(identifier) { const result = this.getPrimitivesFromMap(identifier); if (!result) { return []; } else { return result; } } /** * Returns a set of primitives which corresponds to the given identifier. * * */ getPrimitivesFromMap(identifier) { if (identifier instanceof Uint8Array) { identifier = [...identifier].toString(); } return this.identifierToPrimitivesMap.get(identifier); } /** * Add primitive to map. * */ addPrimitiveToMap(entry) { const identifier = entry.getIdentifier(); const id = [...identifier].toString(); const existing = this.getPrimitivesFromMap(id); if (!existing) { this.identifierToPrimitivesMap.set(id, [entry]); } else { existing.push(entry); this.identifierToPrimitivesMap.set(id, existing); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbWl0aXZlX3NldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2ludGVybmFsL3ByaW1pdGl2ZV9zZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGlDQUFpQyxDQUFDO0FBRWxFLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM3QyxPQUFPLEVBQWMsZUFBZSxFQUFxQixNQUFNLFNBQVMsQ0FBQztBQUd6RTs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sS0FBSztJQUNoQixZQUNxQixTQUFZLEVBQW1CLFVBQXNCLEVBQ3JELFNBQTBCLEVBQzFCLGdCQUFvQztRQUZwQyxjQUFTLEdBQVQsU0FBUyxDQUFHO1FBQW1CLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDckQsY0FBUyxHQUFULFNBQVMsQ0FBaUI7UUFDMUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFvQjtJQUFHLENBQUM7SUFFN0QsWUFBWTtRQUNWLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN4QixDQUFDO0lBRUQsYUFBYTtRQUNYLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO0lBRUQsWUFBWTtRQUNWLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN4QixDQUFDO0lBRUQsbUJBQW1CO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFPdkIsWUFBNkIsYUFBNkI7UUFBN0Isa0JBQWEsR0FBYixhQUFhLENBQWdCO1FBTmxELFlBQU8sR0FBa0IsSUFBSSxDQUFDO1FBT3BDLElBQUksQ0FBQyx5QkFBeUIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzdDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxnQkFB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TSxFQUFFLEdBQUcsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2IsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQ2pEO2FBQU07WUFDTCxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JCLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQ2xEO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuXG5pbXBvcnQge1NlY3VyaXR5RXhjZXB0aW9ufSBmcm9tICcuLi9leGNlcHRpb24vc2VjdXJpdHlfZXhjZXB0aW9uJztcblxuaW1wb3J0IHtDcnlwdG9Gb3JtYXR9IGZyb20gJy4vY3J5cHRvX2Zvcm1hdCc7XG5pbXBvcnQge1BiS2V5c2V0S2V5LCBQYktleVN0YXR1c1R5cGUsIFBiT3V0cHV0UHJlZml4VHlwZX0gZnJvbSAnLi9wcm90byc7XG5pbXBvcnQge0NvbnN0cnVjdG9yfSBmcm9tICcuL3V0aWwnO1xuXG4vKipcbiAqIEF1eGlsaWFyeSBjbGFzcyBmb3IgUHJpbWl0aXZlU2V0XG4gKiBFbnRyeS1vYmplY3RzIGhvbGQgaW5kaXZpZHVhbCBpbnN0YW5jZXMgb2YgcHJpbWl0aXZlcyBpbiB0aGUgc2V0LlxuICpcbiAqIEB0ZW1wbGF0ZSBQXG4gKiBAZmluYWxcbiAqL1xuZXhwb3J0IGNsYXNzIEVudHJ5PFA+IHtcbiAgY29uc3RydWN0b3IoXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IHByaW1pdGl2ZTogUCwgcHJpdmF0ZSByZWFkb25seSBpZGVudGlmaWVyOiBVaW50OEFycmF5LFxuICAgICAgcHJpdmF0ZSByZWFkb25seSBrZXlTdGF0dXM6IFBiS2V5U3RhdHVzVHlwZSxcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgb3V0cHV0UHJlZml4VHlwZTogUGJPdXRwdXRQcmVmaXhUeXBlKSB7fVxuXG4gIGdldFByaW1pdGl2ZSgpOiBQIHtcbiAgICByZXR1cm4gdGhpcy5wcmltaXRpdmU7XG4gIH1cblxuICBnZXRJZGVudGlmaWVyKCk6IFVpbnQ4QXJyYXkge1xuICAgIHJldHVybiB0aGlzLmlkZW50aWZpZXI7XG4gIH1cblxuICBnZXRLZXlTdGF0dXMoKTogUGJLZXlTdGF0dXNUeXBlIHtcbiAgICByZXR1cm4gdGhpcy5rZXlTdGF0dXM7XG4gIH1cblxuICBnZXRPdXRwdXRQcmVmaXhUeXBlKCk6IFBiT3V0cHV0UHJlZml4VHlwZSB7XG4gICAgcmV0dXJuIHRoaXMub3V0cHV0UHJlZml4VHlwZTtcbiAgfVxufVxuXG4vKipcbiAqIEEgY29udGFpbmVyIGNsYXNzIGZvciBhIHNldCBvZiBwcmltaXRpdmVzIChpLmUuIGltcGxlbWVudGF0aW9ucyBvZlxuICogY3J5cHRvZ3JhcGhpYyBwcmltaXRpdmVzIG9mZmVyZWQgYnkgVGluaykuIEl0IHByb3ZpZGVzIGFsc28gYWRkaXRpb25hbFxuICogcHJvcGVydGllcyBmb3IgdGhlIHByaW1pdGl2ZXMgaXQgaG9sZHMuIEluIHBhcnRpY3VsYXIsIG9uZSBvZiB0aGUgcHJpbWl0aXZlc1xuICogaW4gdGhlIHNldCBjYW4gYmUgZGlzdGluZ3Vpc2hlZCBhcyBcInRoZSBwcmltYXJ5XCIgb25lLlxuICpcbiAqIFByaW1pdGl2ZVNldCBpcyBhbiBhdXhpbGlhcnkgY2xhc3MgdXNlZCBmb3Igc3VwcG9ydGluZyBrZXkgcm90YXRpb246XG4gKiBwcmltaXRpdmVzIGluIGEgc2V0IGNvcnJlc3BvbmQgdG8ga2V5cyBpbiBhIGtleXNldC4gVXNlcnMgd2lsbCB1c3VhbGx5IHdvcmtcbiAqIHdpdGggcHJpbWl0aXZlIGluc3RhbmNlcyB3aGljaCBlc3NlbnRpYWxseSB3cmFwIHByaW1pdGl2ZSBzZXRzLiBGb3IgZXhhbXBsZVxuICogYW4gaW5zdGFuY2Ugb2YgYW4gQWVhZC1wcmltaXRpdmUgZm9yIGEgZ2l2ZW4ga2V5c2V0IGhvbGRzIGEgc2V0IG9mXG4gKiBBZWFkLXByaW1pdGl2ZXMgY29ycmVzcG9uZGluZyB0byB0aGUga2V5cyBpbiB0aGUga2V5c2V0LCBhbmQgdXNlcyB0aGUgc2V0XG4gKiBtZW1iZXJzIHRvIGRvIHRoZSBhY3R1YWwgY3J5cHRvIG9wZXJhdGlvbnM6IHRvIGVuY3J5cHQgZGF0YSB0aGUgcHJpbWFyeVxuICogQWVhZC1wcmltaXRpdmUgZnJvbSB0aGUgc2V0IGlzIHVzZWQsIGFuZCB1cG9uIGRlY3J5cHRpb24gdGhlIGNpcGhlcnRleHQnc1xuICogcHJlZml4IGRldGVybWluZXMgdGhlIGlkZW50aWZpZXIgb2YgdGhlIHByaW1pdGl2ZSBmcm9tIHRoZSBzZXQuXG4gKlxuICogUHJpbWl0aXZlU2V0IGlzIGEgcHVibGljIGNsYXNzIHRvIGFsbG93IGl0cyB1c2UgaW4gaW1wbGVtZW50YXRpb25zIG9mIGN1c3RvbVxuICogcHJpbWl0aXZlcy5cbiAqXG4gKiBAZmluYWxcbiAqL1xuZXhwb3J0IGNsYXNzIFByaW1pdGl2ZVNldDxQPiB7XG4gIHByaXZhdGUgcHJpbWFyeTogRW50cnk8UD58bnVsbCA9IG51bGw7XG5cbiAgLy8gS2V5cyBoYXZlIHRvIGJlIHN0b3JlZCBhcyBzdHJpbmdzIGFzIHR3byBVaW50OEFycmF5cyBob2xkaW5nIHRoZSBzYW1lXG4gIC8vIGRpZ2l0cyBhcmUgc3RpbGwgZGlmZmVyZW50IG9iamVjdHMuXG4gIHByaXZhdGUgcmVhZG9ubHkgaWRlbnRpZmllclRvUHJpbWl0aXZlc01hcDogTWFwPHN0cmluZywgQXJyYXk8RW50cnk8UD4+PjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByaW1pdGl2ZVR5cGU6IENvbnN0cnVjdG9yPFA+KSB7XG4gICAgdGhpcy5pZGVudGlmaWVyVG9QcmltaXRpdmVzTWFwID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHR5cGUgb2YgcHJpbWl0aXZlcyBjb250YWluZWQgaW4gdGhpcyBzZXQuXG4gICAqXG4gICAqL1xuICBnZXRQcmltaXRpdmVUeXBlKCk6IENvbnN0cnVjdG9yPFA+IHtcbiAgICByZXR1cm4gdGhpcy5wcmltaXRpdmVUeXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gZW50cnkgaW4gdGhlIHByaW1pdGl2ZSB0YWJsZSBhbmQgcmV0dXJucyBpdC5cbiAgICpcbiAgICpcbiAgICovXG4gIGFkZFByaW1pdGl2ZShwcmltaXRpdmU6IFAsIGtleTogUGJLZXlzZXRLZXkpOiBFbnRyeTxQPiB7XG4gICAgaWYgKCFwcmltaXRpdmUpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignUHJpbWl0aXZlIGhhcyB0byBiZSBub24gbnVsbC4nKTtcbiAgICB9XG4gICAgaWYgKCFrZXkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignS2V5IGhhcyB0byBiZSBub24gbnVsbC4nKTtcbiAgICB9XG4gICAgY29uc3QgaWRlbnRpZmllciA9IENyeXB0b0Zvcm1hdC5nZXRPdXRwdXRQcmVmaXgoa2V5KTtcbiAgICBjb25zdCBlbnRyeSA9IG5ldyBFbnRyeShcbiAgICAgICAgcHJpbWl0aXZlLCBpZGVudGlmaWVyLCBrZXkuZ2V0U3RhdHVzKCksIGtleS5nZXRPdXRwdXRQcmVmaXhUeXBlKCkpO1xuICAgIHRoaXMuYWRkUHJpbWl0aXZlVG9NYXAoZW50cnkpO1xuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBlbnRyeSB3aXRoIHRoZSBwcmltYXJ5IHByaW1pdGl2ZS5cbiAgICpcbiAgICovXG4gIGdldFByaW1hcnkoKTogRW50cnk8UD58bnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucHJpbWFyeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGdpdmVuIEVudHJ5IGFzIHRoZSBwcmltYXJ5IG9uZS5cbiAgICpcbiAgICovXG4gIHNldFByaW1hcnkocHJpbWl0aXZlOiBFbnRyeTxQPikge1xuICAgIGlmICghcHJpbWl0aXZlKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1ByaW1hcnkgY2Fubm90IGJlIHNldCB0byBudWxsLicpO1xuICAgIH1cbiAgICBpZiAocHJpbWl0aXZlLmdldEtleVN0YXR1cygpICE9IFBiS2V5U3RhdHVzVHlwZS5FTkFCTEVEKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1ByaW1hcnkgaGFzIHRvIGJlIGVuYWJsZWQuJyk7XG4gICAgfVxuXG4gICAgLy8gVGhlcmUgaGFzIHRvIGJlIGV4YWN0bHkgb25lIGtleSBlbmFibGVkIHdpdGggdGhpcyBpZGVudGlmaWVyLlxuICAgIGNvbnN0IGVudHJpZXMgPSB0aGlzLmdldFByaW1pdGl2ZXMocHJpbWl0aXZlLmdldElkZW50aWZpZXIoKSk7XG4gICAgbGV0IGVudHJ5Rm91bmQgPSBmYWxzZTtcbiAgICBjb25zdCBlbnRyaWVzTGVuZ3RoID0gZW50cmllcy5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbnRyaWVzTGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChlbnRyaWVzW2ldLmdldEtleVN0YXR1cygpID09PSBQYktleVN0YXR1c1R5cGUuRU5BQkxFRCkge1xuICAgICAgICBlbnRyeUZvdW5kID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghZW50cnlGb3VuZCkge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKFxuICAgICAgICAgICdQcmltYXJ5IGNhbm5vdCBiZSBzZXQgdG8gYW4gZW50cnkgd2hpY2ggaXMgJyArXG4gICAgICAgICAgJ25vdCBoZWxkIGJ5IHRoaXMgcHJpbWl0aXZlIHNldC4nKTtcbiAgICB9XG4gICAgdGhpcy5wcmltYXJ5ID0gcHJpbWl0aXZlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIHByaW1pdGl2ZXMgdXNpbmcgUkFXIHByZWZpeC5cbiAgICpcbiAgICovXG4gIGdldFJhd1ByaW1pdGl2ZXMoKTogQXJyYXk8RW50cnk8UD4+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRQcmltaXRpdmVzKENyeXB0b0Zvcm1hdC5SQVdfUFJFRklYKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBlbnRyaWVzIHdpdGggcHJpbWl0aXZlIGlkZW50aWZpZWQgd2l0aCBpZGVudGlmaWVyLlxuICAgKlxuICAgKlxuICAgKi9cbiAgZ2V0UHJpbWl0aXZlcyhpZGVudGlmaWVyOiBVaW50OEFycmF5KTogQXJyYXk8RW50cnk8UD4+IHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLmdldFByaW1pdGl2ZXNGcm9tTWFwKGlkZW50aWZpZXIpO1xuICAgIGlmICghcmVzdWx0KSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzZXQgb2YgcHJpbWl0aXZlcyB3aGljaCBjb3JyZXNwb25kcyB0byB0aGUgZ2l2ZW4gaWRlbnRpZmllci5cbiAgICpcbiAgICpcbiAgICovXG4gIHByaXZhdGUgZ2V0UHJpbWl0aXZlc0Zyb21NYXAoaWRlbnRpZmllcjogVWludDhBcnJheXxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmcpOiBBcnJheTxFbnRyeTxQPj58dW5kZWZpbmVkIHtcbiAgICBpZiAoaWRlbnRpZmllciBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgIGlkZW50aWZpZXIgPSBbLi4uaWRlbnRpZmllcl0udG9TdHJpbmcoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaWRlbnRpZmllclRvUHJpbWl0aXZlc01hcC5nZXQoaWRlbnRpZmllcik7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHByaW1pdGl2ZSB0byBtYXAuXG4gICAqXG4gICAqL1xuICBwcml2YXRlIGFkZFByaW1pdGl2ZVRvTWFwKGVudHJ5OiBFbnRyeTxQPikge1xuICAgIGNvbnN0IGlkZW50aWZpZXIgPSBlbnRyeS5nZXRJZGVudGlmaWVyKCk7XG4gICAgY29uc3QgaWQgPSBbLi4uaWRlbnRpZmllcl0udG9TdHJpbmcoKTtcbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMuZ2V0UHJpbWl0aXZlc0Zyb21NYXAoaWQpO1xuICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuaWRlbnRpZmllclRvUHJpbWl0aXZlc01hcC5zZXQoaWQsIFtlbnRyeV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBleGlzdGluZy5wdXNoKGVudHJ5KTtcbiAgICAgIHRoaXMuaWRlbnRpZmllclRvUHJpbWl0aXZlc01hcC5zZXQoaWQsIGV4aXN0aW5nKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==