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