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.
710 lines • 83.1 kB
JavaScript
/**
* @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());
});
};
/**
* @fileoverview Common enums.
*/
import { InvalidArgumentsException } from '../exception/invalid_arguments_exception';
import { SecurityException } from '../exception/security_exception';
import * as Bytes from './bytes';
/**
* Supported elliptic curves.
*/
export var CurveType;
(function (CurveType) {
CurveType[CurveType["P256"] = 1] = "P256";
CurveType[CurveType["P384"] = 2] = "P384";
CurveType[CurveType["P521"] = 3] = "P521";
})(CurveType || (CurveType = {}));
/**
* Supported point format.
*/
export var PointFormatType;
(function (PointFormatType) {
PointFormatType[PointFormatType["UNCOMPRESSED"] = 1] = "UNCOMPRESSED";
PointFormatType[PointFormatType["COMPRESSED"] = 2] = "COMPRESSED";
// Like UNCOMPRESSED but without the \x04 prefix. Crunchy uses this format.
// DO NOT USE unless you are a Crunchy user moving to Tink.
PointFormatType[PointFormatType["DO_NOT_USE_CRUNCHY_UNCOMPRESSED"] = 3] = "DO_NOT_USE_CRUNCHY_UNCOMPRESSED";
})(PointFormatType || (PointFormatType = {}));
/**
* Supported ECDSA signature encoding.
*/
export var EcdsaSignatureEncodingType;
(function (EcdsaSignatureEncodingType) {
// The DER signature is encoded using ASN.1
// (https://tools.ietf.org/html/rfc5480#appendix-A):
// ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }. In particular, the
// encoding is:
// 0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s.
EcdsaSignatureEncodingType[EcdsaSignatureEncodingType["DER"] = 1] = "DER";
// The IEEE_P1363 signature's format is r || s, where r and s are zero-padded
// and have the same size in bytes as the order of the curve. For example, for
// NIST P-256 curve, r and s are zero-padded to 32 bytes.
EcdsaSignatureEncodingType[EcdsaSignatureEncodingType["IEEE_P1363"] = 2] = "IEEE_P1363";
})(EcdsaSignatureEncodingType || (EcdsaSignatureEncodingType = {}));
/**
* Transform an ECDSA signature in DER encoding to IEEE P1363 encoding.
*
* @param der the ECDSA signature in DER encoding
* @param ieeeLength the length of the ECDSA signature in IEEE
* encoding. This is usually 2 * size of the elliptic curve field.
* @return ECDSA signature in IEEE encoding
*/
export function ecdsaDer2Ieee(der, ieeeLength) {
if (!isValidDerEcdsaSignature(der)) {
throw new SecurityException('invalid DER signature');
}
if (!Number.isInteger(ieeeLength) || ieeeLength < 0) {
throw new InvalidArgumentsException('ieeeLength must be a nonnegative integer');
}
const ieee = new Uint8Array(ieeeLength);
const length = der[1] & 255;
let offset = 1 +
/* 0x30 */
1;
/* totalLength */
if (length >= 128) {
offset++;
}
// Long form length
offset++;
// 0x02
const rLength = der[offset++];
let extraZero = 0;
if (der[offset] === 0) {
extraZero = 1;
}
const rOffset = ieeeLength / 2 - rLength + extraZero;
ieee.set(der.subarray(offset + extraZero, offset + rLength), rOffset);
offset += rLength +
/* r byte array */
1;
/* 0x02 */
const sLength = der[offset++];
extraZero = 0;
if (der[offset] === 0) {
extraZero = 1;
}
const sOffset = ieeeLength - sLength + extraZero;
ieee.set(der.subarray(offset + extraZero, offset + sLength), sOffset);
return ieee;
}
/**
* Transform an ECDSA signature in IEEE 1363 encoding to DER encoding.
*
* @param ieee the ECDSA signature in IEEE encoding
* @return ECDSA signature in DER encoding
*/
export function ecdsaIeee2Der(ieee) {
if (ieee.length % 2 != 0 || ieee.length == 0 || ieee.length > 132) {
throw new SecurityException('Invalid IEEE P1363 signature encoding. Length: ' + ieee.length);
}
const r = toUnsignedBigNum(ieee.subarray(0, ieee.length / 2));
const s = toUnsignedBigNum(ieee.subarray(ieee.length / 2, ieee.length));
let offset = 0;
const length = 1 + 1 + r.length + 1 + 1 + s.length;
let der;
if (length >= 128) {
der = new Uint8Array(length + 3);
der[offset++] = 48;
der[offset++] = 128 + 1;
der[offset++] = length;
}
else {
der = new Uint8Array(length + 2);
der[offset++] = 48;
der[offset++] = length;
}
der[offset++] = 2;
der[offset++] = r.length;
der.set(r, offset);
offset += r.length;
der[offset++] = 2;
der[offset++] = s.length;
der.set(s, offset);
return der;
}
/**
* Validate that the ECDSA signature is in DER encoding, based on
* https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki.
*
* @param sig an ECDSA siganture
*/
export function isValidDerEcdsaSignature(sig) {
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
// * total-length: 1-byte or 2-byte length descriptor of everything that
// follows.
// * R-length: 1-byte length descriptor of the R value that follows.
// * R: arbitrary-length big-endian encoded R value. It must use the shortest
// possible encoding for a positive integers (which means no null bytes at
// the start, except a single one when the next byte has its highest bit
// set).
// * S-length: 1-byte length descriptor of the S value that follows.
// * S: arbitrary-length big-endian encoded S value. The same rules apply.
/* S */
if (sig.length < 1 +
/* 0x30 */
1 +
/* total-length */
1 +
/* 0x02 */
1 +
/* R-length */
1 +
/* R */
1 +
/* 0x02 */
1 +
/* S-length */
1) {
// Signature is too short.
return false;
}
// Checking bytes from left to right.
// byte #1: a signature is of type 0x30 (compound).
if (sig[0] != 48) {
return false;
}
// byte #2 and maybe #3: the total length of the signature.
let totalLen = sig[1] & 255;
let totalLenLen = 1;
// the length of the total length field, could be 2-byte.
if (totalLen == 129) {
// The signature is >= 128 bytes thus total length field is in long-form
// encoding and occupies 2 bytes.
totalLenLen = 2;
// byte #3 is the total length.
totalLen = sig[2] & 255;
if (totalLen < 128) {
// Length in long-form encoding must be >= 128.
return false;
}
}
else if (totalLen == 128 || totalLen > 129) {
// Impossible values for the second byte.
return false;
}
// Make sure the length covers the entire sig.
if (totalLen != sig.length - 1 - totalLenLen) {
return false;
}
// Start checking R.
// Check whether the R element is an integer.
if (sig[1 + totalLenLen] != 2) {
return false;
}
// Extract the length of the R element.
const rLen = sig[1 +
/* 0x30 */
totalLenLen + 1] &
/* 0x02 */
255;
// Make sure the length of the S element is still inside the signature.
if (1 +
/* 0x30 */
totalLenLen + 1 +
/* 0x02 */
1 +
/* rLen */
rLen + 1 >=
/* 0x02 */
sig.length) {
return false;
}
// Zero-length integers are not allowed for R.
if (rLen == 0) {
return false;
}
// Negative numbers are not allowed for R.
if ((sig[3 + totalLenLen] & 255) >= 128) {
return false;
}
// Null bytes at the start of R are not allowed, unless R would
// otherwise be interpreted as a negative number.
if (rLen > 1 && sig[3 + totalLenLen] == 0 &&
(sig[4 + totalLenLen] & 255) < 128) {
return false;
}
// Start checking S.
// Check whether the S element is an integer.
if (sig[3 + totalLenLen + rLen] != 2) {
return false;
}
// Extract the length of the S element.
const sLen = sig[1 +
/* 0x30 */
totalLenLen + 1 +
/* 0x02 */
1 +
/* rLen */
rLen + 1] &
/* 0x02 */
255;
// Verify that the length of the signature matches the sum of the length of
// the elements.
if (1 +
/* 0x30 */
totalLenLen + 1 +
/* 0x02 */
1 +
/* rLen */
rLen + 1 +
/* 0x02 */
1 +
/* sLen */
sLen !=
sig.length) {
return false;
}
// Zero-length integers are not allowed for S.
if (sLen == 0) {
return false;
}
// Negative numbers are not allowed for S.
if ((sig[5 + totalLenLen + rLen] & 255) >= 128) {
return false;
}
// Null bytes at the start of S are not allowed, unless S would
// otherwise be interpreted as a negative number.
if (sLen > 1 && sig[5 + totalLenLen + rLen] == 0 &&
(sig[6 + totalLenLen + rLen] & 255) < 128) {
return false;
}
return true;
}
/**
* Transform a big integer in big endian to minimal unsigned form which has
* no extra zero at the beginning except when the highest bit is set.
*
*/
function toUnsignedBigNum(bytes) {
// Remove zero prefixes.
let start = 0;
while (start < bytes.length && bytes[start] == 0) {
start++;
}
if (start == bytes.length) {
start = bytes.length - 1;
}
let extraZero = 0;
// If the 1st bit is not zero, add 1 zero byte.
if ((bytes[start] & 128) == 128) {
// Add extra zero.
extraZero = 1;
}
const res = new Uint8Array(bytes.length - start + extraZero);
res.set(bytes.subarray(start), extraZero);
return res;
}
export function curveToString(curve) {
switch (curve) {
case CurveType.P256:
return 'P-256';
case CurveType.P384:
return 'P-384';
case CurveType.P521:
return 'P-521';
}
}
export function curveFromString(curve) {
switch (curve) {
case 'P-256':
return CurveType.P256;
case 'P-384':
return CurveType.P384;
case 'P-521':
return CurveType.P521;
}
throw new InvalidArgumentsException('unknown curve: ' + curve);
}
/** Helper method for unit tests. */
export function formatFromString(format) {
switch (format) {
case 'UNCOMPRESSED':
return PointFormatType.UNCOMPRESSED;
case 'DO_NOT_USE_CRUNCHY_UNCOMPRESSED':
return PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED;
case 'COMPRESSED':
return PointFormatType.COMPRESSED;
default:
throw new InvalidArgumentsException('unknown format: ' + format);
}
}
export function pointEncode(curve, format, point) {
const fieldSize = fieldSizeInBytes(curveFromString(curve));
switch (format) {
case PointFormatType.UNCOMPRESSED: {
const { x, y } = point;
if (x === undefined) {
throw new InvalidArgumentsException('x must be provided');
}
if (y === undefined) {
throw new InvalidArgumentsException('y must be provided');
}
const result = new Uint8Array(1 + 2 * fieldSize);
result[0] = 4;
result.set(
/* opt_webSafe = */
Bytes.fromBase64(x, true), 1);
result.set(
/* opt_webSafe = */
Bytes.fromBase64(y, true), 1 + fieldSize);
return result;
}
case PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED: {
const { x, y } = point;
if (x === undefined) {
throw new InvalidArgumentsException('x must be provided');
}
if (y === undefined) {
throw new InvalidArgumentsException('y must be provided');
}
let decodedX = Bytes.fromBase64(x, /* opt_webSafe = */ true);
let decodedY = Bytes.fromBase64(y, /* opt_webSafe = */ true);
if (decodedX.length > fieldSize) {
// x has leading 0's, strip them.
decodedX = decodedX.slice(decodedX.length - fieldSize, decodedX.length);
}
if (decodedY.length > fieldSize) {
// y has leading 0's, strip them.
decodedY = decodedY.slice(decodedY.length - fieldSize, decodedY.length);
}
const result = new Uint8Array(2 * fieldSize);
result.set(decodedX, 0);
result.set(decodedY, fieldSize);
return result;
}
case PointFormatType.COMPRESSED: {
const { x, y } = point;
if (x === undefined) {
throw new InvalidArgumentsException('x must be provided');
}
if (y === undefined) {
throw new InvalidArgumentsException('y must be provided');
}
let decodedX = Bytes.fromBase64(x, /* opt_webSafe = */ true);
let decodedY = Bytes.fromBase64(y, /* opt_webSafe = */ true);
if (decodedX.length > fieldSize) {
// x has leading 0's, strip them.
decodedX = decodedX.slice(decodedX.length - fieldSize, decodedX.length);
}
if (decodedY.length > fieldSize) {
// y has leading 0's, strip them.
decodedY = decodedY.slice(decodedY.length - fieldSize, decodedY.length);
}
const result = new Uint8Array(1 + fieldSize);
result.set(decodedX, /* offset = */ 1 + fieldSize - decodedX.length);
result[0] = testBit(byteArrayToInteger(decodedY), 0) ? 3 : 2;
return result;
}
default:
throw new SecurityException('invalid format');
}
}
function getModulus(curve) {
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (Appendix D).
switch (curve) {
case CurveType.P256:
return BigInt('115792089210356248762697446949407573530086143415290314195533631308' +
'867097853951');
case CurveType.P384:
return BigInt('394020061963944792122790401001436138050797392704654466679482934042' +
'45721771496870329047266088258938001861606973112319');
case CurveType.P521:
return BigInt('686479766013060971498190079908139321726943530014330540939446345918' +
'55431833976560521225596406614545549772963113914808580371219879' +
'99716643812574028291115057151');
default:
throw new InvalidArgumentsException('invalid curve');
}
}
function getB(curve) {
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (Appendix D).
switch (curve) {
case CurveType.P256:
return BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b');
case CurveType.P384:
return BigInt('0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a' +
'c656398d8a2ed19d2a85c8edd3ec2aef');
case CurveType.P521:
return BigInt('0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10' +
'9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b5' +
'03f00');
default:
throw new InvalidArgumentsException('invalid curve');
}
}
/** Converts byte array to bigint. */
export function byteArrayToInteger(bytes) {
return BigInt('0x' + Bytes.toHex(bytes));
}
/** Converts bigint to byte array. */
export function integerToByteArray(i) {
let input = i.toString(16);
// If necessary, prepend leading zero to ensure that input length is even.
input = input.length % 2 === 0 ? input : '0' + input;
return Bytes.fromHex(input);
}
/** Returns true iff the ith bit (in lsb order) of n is set. */
function testBit(n, i) {
const m = BigInt(1) << BigInt(i);
return (n & m) !== BigInt(0);
}
/**
* Computes a modular exponent. Since JavaScript BigInt operations are not
* constant-time, information about the inputs could leak. Therefore, THIS
* METHOD SHOULD ONLY BE USED FOR POINT DECOMPRESSION.
*
* @param b base
* @param exp exponent
* @param p modulus
* @return b^exp modulo p
*/
function modPow(b, exp, p) {
if (exp === BigInt(0)) {
return BigInt(1);
}
let result = b;
const exponentBitString = exp.toString(2);
for (let i = 1; i < exponentBitString.length; ++i) {
result = (result * result) % p;
if (exponentBitString[i] === '1') {
result = (result * b) % p;
}
}
return result;
}
/**
* Computes a square root modulo an odd prime. Since timing and exceptions can
* leak information about the inputs, THIS METHOD SHOULD ONLY BE USED FOR
* POINT DECOMPRESSION.
*
* @param x square
* @param p prime modulus
* @return square root of x modulo p
*/
function modSqrt(x, p) {
if (p <= BigInt(0)) {
throw new InvalidArgumentsException('p must be positive');
}
const base = x % p;
// The currently supported NIST curves P-256, P-384, and P-521 all satisfy
// p % 4 == 3. However, although currently a no-op, the following check
// should be left in place in case other curves are supported in the future.
if (testBit(p, 0) && /* istanbul ignore next */ testBit(p, 1)) {
// Case p % 4 == 3 (applies to NIST curves P-256, P-384, and P-521)
// q = (p + 1) / 4
const q = (p + BigInt(1)) >> BigInt(2);
const squareRoot = modPow(base, q, p);
if ((squareRoot * squareRoot) % p !== base) {
throw new SecurityException('could not find a modular square root');
}
return squareRoot;
}
// Skipping other elliptic curve types that require Cipolla's algorithm.
throw new InvalidArgumentsException('unsupported modulus value');
}
/**
* Computes the y-coordinate of a point on an elliptic curve given its
* x-coordinate. Since timing and exceptions can leak information about the
* inputs, THIS METHOD SHOULD ONLY BE USED FOR POINT DECOMPRESSION.
*
* @param x x-coordinate
* @param lsb least significant bit of the y-coordinate
* @param curve NIST curve P-256, P-384, or P-521
* @return y-coordinate
*/
function getY(x, lsb, curve) {
const p = getModulus(curveFromString(curve));
const a = p - BigInt(3);
const b = getB(curveFromString(curve));
const rhs = (((x * x) + a) * x + b) % p;
let y = modSqrt(rhs, p);
if (lsb !== testBit(y, 0)) {
y = (p - y) % p;
}
return y;
}
export function pointDecode(curve, format, point) {
const fieldSize = fieldSizeInBytes(curveFromString(curve));
switch (format) {
case PointFormatType.UNCOMPRESSED: {
if (point.length !== 1 + 2 * fieldSize || point[0] !== 4) {
throw new SecurityException('invalid point');
}
const result = {
'kty': 'EC',
'crv': curve,
'x': Bytes.toBase64(new Uint8Array(point.subarray(1, 1 + fieldSize)),
/* websafe */
true),
'y': Bytes.toBase64(new Uint8Array(point.subarray(1 + fieldSize, point.length)),
/* websafe */
true),
'ext': true
};
return result;
}
case PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED: {
if (point.length !== 2 * fieldSize) {
throw new SecurityException('invalid point');
}
const result = {
'kty': 'EC',
'crv': curve,
'x': Bytes.toBase64(new Uint8Array(point.subarray(0, fieldSize)), /* websafe */ true),
'y': Bytes.toBase64(new Uint8Array(point.subarray(fieldSize, point.length)),
/* websafe */ true),
'ext': true
};
return result;
}
case PointFormatType.COMPRESSED: {
if (point.length !== 1 + fieldSize) {
throw new SecurityException('compressed point has wrong length');
}
if (point[0] !== 2 && point[0] !== 3) {
throw new SecurityException('invalid format');
}
const lsb = (point[0] === 3); // point[0] must be 2 (false) or 3 (true).
const x = byteArrayToInteger(point.subarray(1, point.length));
const p = getModulus(curveFromString(curve));
if (x < BigInt(0) || x >= p) {
throw new SecurityException('x is out of range');
}
const y = getY(x, lsb, curve);
const result = {
'kty': 'EC',
'crv': curve,
'x': Bytes.toBase64(integerToByteArray(x), /* websafe */ true),
'y': Bytes.toBase64(integerToByteArray(y), /* websafe */ true),
'ext': true
};
return result;
}
default:
throw new SecurityException('invalid format');
}
}
export function getJsonWebKey(curve, x, y, d) {
const key = {
'kty': 'EC',
'crv': curveToString(curve),
'x': Bytes.toBase64(x,
/* websafe */
true),
'y': Bytes.toBase64(y,
/* websafe */
true),
'ext': true
};
if (d) {
key['d'] = Bytes.toBase64(d,
/* websafe */
true);
}
return key;
}
export function fieldSizeInBytes(curve) {
switch (curve) {
case CurveType.P256:
return 32;
case CurveType.P384:
return 48;
case CurveType.P521:
return 66;
}
}
export function encodingSizeInBytes(curve, pointFormat) {
switch (pointFormat) {
case PointFormatType.UNCOMPRESSED:
return 2 * fieldSizeInBytes(curve) + 1;
case PointFormatType.COMPRESSED:
return fieldSizeInBytes(curve) + 1;
case PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED:
return 2 * fieldSizeInBytes(curve);
}
}
export function computeEcdhSharedSecret(privateKey, publicKey) {
return __awaiter(this, void 0, void 0, function* () {
const { namedCurve } = privateKey.algorithm;
if (!namedCurve) {
throw new InvalidArgumentsException('namedCurve must be provided');
}
const ecdhParams = Object.assign({ 'public': publicKey }, privateKey.algorithm);
const fieldSizeInBits = 8 * fieldSizeInBytes(curveFromString(namedCurve));
const sharedSecret = yield window.crypto.subtle.deriveBits(ecdhParams, privateKey, fieldSizeInBits);
return new Uint8Array(sharedSecret);
});
}
export function generateKeyPair(algorithm, curve) {
return __awaiter(this, void 0, void 0, function* () {
if (algorithm != 'ECDH' && algorithm != 'ECDSA') {
throw new InvalidArgumentsException('algorithm must be either ECDH or ECDSA');
}
const params = { 'name': algorithm, 'namedCurve': curve };
const ephemeralKeyPair = yield window.crypto.subtle.generateKey(params, /* extractable= */ true, algorithm == 'ECDH' ? ['deriveKey', 'deriveBits'] : ['sign', 'verify']);
return ephemeralKeyPair;
});
}
export function exportCryptoKey(cryptoKey) {
return __awaiter(this, void 0, void 0, function* () {
const jwk = yield window.crypto.subtle.exportKey('jwk', cryptoKey);
return (jwk);
});
}
export function importPublicKey(algorithm, jwk) {
return __awaiter(this, void 0, void 0, function* () {
if (algorithm != 'ECDH' && algorithm != 'ECDSA') {
throw new InvalidArgumentsException('algorithm must be either ECDH or ECDSA');
}
const { crv } = jwk;
if (!crv) {
throw new InvalidArgumentsException('crv must be provided');
}
const publicKey = yield window.crypto.subtle.importKey(
/* format */
'jwk', jwk, { 'name': algorithm, 'namedCurve': crv },
/* algorithm */
true,
/* extractable */
algorithm == 'ECDH' ? [] : ['verify']);
/* usage */
return publicKey;
});
}
export function importPrivateKey(algorithm, jwk) {
return __awaiter(this, void 0, void 0, function* () {
if (algorithm != 'ECDH' && algorithm != 'ECDSA') {
throw new InvalidArgumentsException('algorithm must be either ECDH or ECDSA');
}
const { crv } = jwk;
if (!crv) {
throw new InvalidArgumentsException('crv must be provided');
}
const privateKey = yield window.crypto.subtle.importKey(
/* format */
'jwk', jwk,
/* key material */
{ 'name': algorithm, 'namedCurve': crv },
/* algorithm */
true,
/* extractable */
algorithm == 'ECDH' ? ['deriveKey', 'deriveBits'] : ['sign']);
/* usage */
return privateKey;
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxsaXB0aWNfY3VydmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3VidGxlL2VsbGlwdGljX2N1cnZlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHOzs7Ozs7Ozs7O0FBR0g7O0dBRUc7QUFFSCxPQUFPLEVBQUMseUJBQXlCLEVBQUMsTUFBTSwwQ0FBMEMsQ0FBQztBQUNuRixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQztBQUVsRSxPQUFPLEtBQUssS0FBSyxNQUFNLFNBQVMsQ0FBQztBQUVqQzs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLFNBSVg7QUFKRCxXQUFZLFNBQVM7SUFDbkIseUNBQVEsQ0FBQTtJQUNSLHlDQUFJLENBQUE7SUFDSix5Q0FBSSxDQUFBO0FBQ04sQ0FBQyxFQUpXLFNBQVMsS0FBVCxTQUFTLFFBSXBCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxlQU9YO0FBUEQsV0FBWSxlQUFlO0lBQ3pCLHFFQUFnQixDQUFBO0lBQ2hCLGlFQUFVLENBQUE7SUFFViwyRUFBMkU7SUFDM0UsMkRBQTJEO0lBQzNELDJHQUErQixDQUFBO0FBQ2pDLENBQUMsRUFQVyxlQUFlLEtBQWYsZUFBZSxRQU8xQjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksMEJBYVg7QUFiRCxXQUFZLDBCQUEwQjtJQUVwQywyQ0FBMkM7SUFDM0Msb0RBQW9EO0lBQ3BELDZFQUE2RTtJQUM3RSxlQUFlO0lBQ2YsNkVBQTZFO0lBQzdFLHlFQUFPLENBQUE7SUFFUCw2RUFBNkU7SUFDN0UsOEVBQThFO0lBQzlFLHlEQUF5RDtJQUN6RCx1RkFBVSxDQUFBO0FBQ1osQ0FBQyxFQWJXLDBCQUEwQixLQUExQiwwQkFBMEIsUUFhckM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxHQUFlLEVBQUUsVUFBa0I7SUFDL0QsSUFBSSxDQUFDLHdCQUF3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