@opentdf/sdk 0.9.0-beta.91 → 0.9.0-beta.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/access/access-fetch.js +1 -2
- package/dist/cjs/src/access/access-rpc.js +1 -3
- package/dist/cjs/src/access.js +1 -14
- package/dist/cjs/src/auth/auth.js +13 -10
- package/dist/cjs/src/auth/dpop.js +121 -0
- package/dist/cjs/src/auth/oidc-clientcredentials-provider.js +37 -3
- package/dist/cjs/src/auth/oidc-externaljwt-provider.js +37 -3
- package/dist/cjs/src/auth/oidc-refreshtoken-provider.js +37 -3
- package/dist/cjs/src/auth/oidc.js +10 -8
- package/dist/cjs/src/auth/providers.js +35 -12
- package/dist/cjs/src/crypto/index.js +16 -2
- package/dist/cjs/src/crypto/pemPublicToCrypto.js +17 -11
- package/dist/cjs/src/opentdf.js +40 -10
- package/dist/cjs/tdf3/index.js +4 -2
- package/dist/cjs/tdf3/src/assertions.js +71 -31
- package/dist/cjs/tdf3/src/ciphers/aes-gcm-cipher.js +1 -1
- package/dist/cjs/tdf3/src/ciphers/symmetric-cipher-base.js +4 -2
- package/dist/cjs/tdf3/src/client/index.js +23 -33
- package/dist/cjs/tdf3/src/crypto/crypto-utils.js +12 -5
- package/dist/cjs/tdf3/src/crypto/declarations.js +1 -1
- package/dist/cjs/tdf3/src/crypto/index.js +849 -88
- package/dist/cjs/tdf3/src/crypto/jose/jwt-claims-set.js +11 -0
- package/dist/cjs/tdf3/src/crypto/jose/validate-crit.js +8 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/buffer_utils.js +41 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/epoch.js +6 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/is_object.js +21 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.js +112 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/secs.js +60 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/lib/validate_crit.js +38 -0
- package/dist/cjs/tdf3/src/crypto/jose/vendor/util/errors.js +135 -0
- package/dist/cjs/tdf3/src/crypto/jwt.js +183 -0
- package/dist/cjs/tdf3/src/crypto/salt.js +14 -8
- package/dist/cjs/tdf3/src/models/encryption-information.js +17 -20
- package/dist/cjs/tdf3/src/models/key-access.js +43 -63
- package/dist/cjs/tdf3/src/tdf.js +75 -75
- package/dist/cjs/tdf3/src/utils/index.js +5 -39
- package/dist/types/src/access/access-fetch.d.ts.map +1 -1
- package/dist/types/src/access/access-rpc.d.ts.map +1 -1
- package/dist/types/src/access.d.ts +0 -5
- package/dist/types/src/access.d.ts.map +1 -1
- package/dist/types/src/auth/auth.d.ts +9 -6
- package/dist/types/src/auth/auth.d.ts.map +1 -1
- package/dist/types/src/auth/dpop.d.ts +60 -0
- package/dist/types/src/auth/dpop.d.ts.map +1 -0
- package/dist/types/src/auth/oidc-clientcredentials-provider.d.ts +3 -2
- package/dist/types/src/auth/oidc-clientcredentials-provider.d.ts.map +1 -1
- package/dist/types/src/auth/oidc-externaljwt-provider.d.ts +3 -2
- package/dist/types/src/auth/oidc-externaljwt-provider.d.ts.map +1 -1
- package/dist/types/src/auth/oidc-refreshtoken-provider.d.ts +3 -2
- package/dist/types/src/auth/oidc-refreshtoken-provider.d.ts.map +1 -1
- package/dist/types/src/auth/oidc.d.ts +6 -4
- package/dist/types/src/auth/oidc.d.ts.map +1 -1
- package/dist/types/src/auth/providers.d.ts +5 -4
- package/dist/types/src/auth/providers.d.ts.map +1 -1
- package/dist/types/src/crypto/index.d.ts +2 -1
- package/dist/types/src/crypto/index.d.ts.map +1 -1
- package/dist/types/src/crypto/pemPublicToCrypto.d.ts +18 -0
- package/dist/types/src/crypto/pemPublicToCrypto.d.ts.map +1 -1
- package/dist/types/src/opentdf.d.ts +13 -4
- package/dist/types/src/opentdf.d.ts.map +1 -1
- package/dist/types/tdf3/index.d.ts +3 -3
- package/dist/types/tdf3/index.d.ts.map +1 -1
- package/dist/types/tdf3/src/assertions.d.ts +23 -8
- package/dist/types/tdf3/src/assertions.d.ts.map +1 -1
- package/dist/types/tdf3/src/ciphers/aes-gcm-cipher.d.ts +3 -3
- package/dist/types/tdf3/src/ciphers/aes-gcm-cipher.d.ts.map +1 -1
- package/dist/types/tdf3/src/ciphers/symmetric-cipher-base.d.ts +4 -4
- package/dist/types/tdf3/src/ciphers/symmetric-cipher-base.d.ts.map +1 -1
- package/dist/types/tdf3/src/client/builders.d.ts +2 -2
- package/dist/types/tdf3/src/client/builders.d.ts.map +1 -1
- package/dist/types/tdf3/src/client/index.d.ts +6 -5
- package/dist/types/tdf3/src/client/index.d.ts.map +1 -1
- package/dist/types/tdf3/src/crypto/crypto-utils.d.ts +14 -4
- package/dist/types/tdf3/src/crypto/crypto-utils.d.ts.map +1 -1
- package/dist/types/tdf3/src/crypto/declarations.d.ts +283 -18
- package/dist/types/tdf3/src/crypto/declarations.d.ts.map +1 -1
- package/dist/types/tdf3/src/crypto/index.d.ts +105 -28
- package/dist/types/tdf3/src/crypto/index.d.ts.map +1 -1
- package/dist/types/tdf3/src/crypto/jose/jwt-claims-set.d.ts +3 -0
- package/dist/types/tdf3/src/crypto/jose/jwt-claims-set.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/validate-crit.d.ts +5 -0
- package/dist/types/tdf3/src/crypto/jose/validate-crit.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/buffer_utils.d.ts +6 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/buffer_utils.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/epoch.d.ts +3 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/epoch.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/is_object.d.ts +3 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/is_object.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.d.ts +3 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/secs.d.ts +3 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/secs.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/validate_crit.d.ts +3 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/lib/validate_crit.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/util/errors.d.ts +76 -0
- package/dist/types/tdf3/src/crypto/jose/vendor/util/errors.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/jwt.d.ts +76 -0
- package/dist/types/tdf3/src/crypto/jwt.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/salt.d.ts +6 -1
- package/dist/types/tdf3/src/crypto/salt.d.ts.map +1 -1
- package/dist/types/tdf3/src/models/encryption-information.d.ts +4 -4
- package/dist/types/tdf3/src/models/encryption-information.d.ts.map +1 -1
- package/dist/types/tdf3/src/models/key-access.d.ts +8 -5
- package/dist/types/tdf3/src/models/key-access.d.ts.map +1 -1
- package/dist/types/tdf3/src/tdf.d.ts +8 -8
- package/dist/types/tdf3/src/tdf.d.ts.map +1 -1
- package/dist/types/tdf3/src/utils/index.d.ts +4 -3
- package/dist/types/tdf3/src/utils/index.d.ts.map +1 -1
- package/dist/web/src/access/access-fetch.js +3 -4
- package/dist/web/src/access/access-rpc.js +3 -5
- package/dist/web/src/access.js +1 -13
- package/dist/web/src/auth/auth.js +13 -10
- package/dist/web/src/auth/dpop.js +118 -0
- package/dist/web/src/auth/oidc-clientcredentials-provider.js +4 -3
- package/dist/web/src/auth/oidc-externaljwt-provider.js +4 -3
- package/dist/web/src/auth/oidc-refreshtoken-provider.js +4 -3
- package/dist/web/src/auth/oidc.js +11 -9
- package/dist/web/src/auth/providers.js +13 -12
- package/dist/web/src/crypto/index.js +4 -2
- package/dist/web/src/crypto/pemPublicToCrypto.js +11 -9
- package/dist/web/src/opentdf.js +7 -10
- package/dist/web/tdf3/index.js +3 -2
- package/dist/web/tdf3/src/assertions.js +71 -31
- package/dist/web/tdf3/src/ciphers/aes-gcm-cipher.js +1 -1
- package/dist/web/tdf3/src/ciphers/symmetric-cipher-base.js +4 -2
- package/dist/web/tdf3/src/client/index.js +25 -35
- package/dist/web/tdf3/src/crypto/crypto-utils.js +12 -5
- package/dist/web/tdf3/src/crypto/declarations.js +1 -1
- package/dist/web/tdf3/src/crypto/index.js +830 -84
- package/dist/web/tdf3/src/crypto/jose/jwt-claims-set.js +5 -0
- package/dist/web/tdf3/src/crypto/jose/validate-crit.js +3 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/lib/buffer_utils.js +35 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/lib/epoch.js +4 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/lib/is_object.js +19 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.js +107 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/lib/secs.js +58 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/lib/validate_crit.js +36 -0
- package/dist/web/tdf3/src/crypto/jose/vendor/util/errors.js +117 -0
- package/dist/web/tdf3/src/crypto/jwt.js +174 -0
- package/dist/web/tdf3/src/crypto/salt.js +13 -7
- package/dist/web/tdf3/src/models/encryption-information.js +11 -14
- package/dist/web/tdf3/src/models/key-access.js +44 -31
- package/dist/web/tdf3/src/tdf.js +71 -71
- package/dist/web/tdf3/src/utils/index.js +5 -6
- package/package.json +11 -4
- package/src/access/access-fetch.ts +2 -8
- package/src/access/access-rpc.ts +0 -7
- package/src/access.ts +0 -17
- package/src/auth/auth.ts +21 -12
- package/src/auth/dpop.ts +222 -0
- package/src/auth/oidc-clientcredentials-provider.ts +23 -15
- package/src/auth/oidc-externaljwt-provider.ts +23 -15
- package/src/auth/oidc-refreshtoken-provider.ts +23 -15
- package/src/auth/oidc.ts +21 -10
- package/src/auth/providers.ts +46 -29
- package/src/crypto/index.ts +21 -1
- package/src/crypto/pemPublicToCrypto.ts +11 -9
- package/src/opentdf.ts +19 -14
- package/tdf3/index.ts +32 -5
- package/tdf3/src/assertions.ts +99 -30
- package/tdf3/src/ciphers/aes-gcm-cipher.ts +7 -2
- package/tdf3/src/ciphers/symmetric-cipher-base.ts +7 -4
- package/tdf3/src/client/builders.ts +2 -2
- package/tdf3/src/client/index.ts +60 -59
- package/tdf3/src/crypto/crypto-utils.ts +15 -8
- package/tdf3/src/crypto/declarations.ts +338 -22
- package/tdf3/src/crypto/index.ts +1021 -118
- package/tdf3/src/crypto/jose/jwt-claims-set.ts +10 -0
- package/tdf3/src/crypto/jose/validate-crit.ts +9 -0
- package/tdf3/src/crypto/jose/vendor/lib/buffer_utils.ts +34 -0
- package/tdf3/src/crypto/jose/vendor/lib/epoch.ts +3 -0
- package/tdf3/src/crypto/jose/vendor/lib/is_object.ts +18 -0
- package/tdf3/src/crypto/jose/vendor/lib/jwt_claims_set.ts +106 -0
- package/tdf3/src/crypto/jose/vendor/lib/secs.ts +57 -0
- package/tdf3/src/crypto/jose/vendor/lib/validate_crit.ts +35 -0
- package/tdf3/src/crypto/jose/vendor/util/errors.ts +101 -0
- package/tdf3/src/crypto/jwt.ts +256 -0
- package/tdf3/src/crypto/salt.ts +16 -8
- package/tdf3/src/models/encryption-information.ts +14 -21
- package/tdf3/src/models/key-access.ts +57 -41
- package/tdf3/src/tdf.ts +110 -93
- package/tdf3/src/utils/index.ts +5 -6
|
@@ -11,17 +11,32 @@ exports.rsaPkcs1Sha256 = rsaPkcs1Sha256;
|
|
|
11
11
|
exports.generateKey = generateKey;
|
|
12
12
|
exports.generateKeyPair = generateKeyPair;
|
|
13
13
|
exports.generateSigningKeyPair = generateSigningKeyPair;
|
|
14
|
-
exports.cryptoToPemPair = cryptoToPemPair;
|
|
15
14
|
exports.encryptWithPublicKey = encryptWithPublicKey;
|
|
16
|
-
exports.generateInitializationVector = generateInitializationVector;
|
|
17
15
|
exports.randomBytes = randomBytes;
|
|
18
16
|
exports.randomBytesAsHex = randomBytesAsHex;
|
|
19
17
|
exports.decryptWithPrivateKey = decryptWithPrivateKey;
|
|
20
18
|
exports.decrypt = decrypt;
|
|
21
19
|
exports.encrypt = encrypt;
|
|
22
|
-
exports.sha256 = sha256;
|
|
23
|
-
exports.hmac = hmac;
|
|
24
20
|
exports.hex2Ab = hex2Ab;
|
|
21
|
+
exports.sign = sign;
|
|
22
|
+
exports.verify = verify;
|
|
23
|
+
exports.digest = digest;
|
|
24
|
+
exports.extractPublicKeyPem = extractPublicKeyPem;
|
|
25
|
+
exports.generateECKeyPair = generateECKeyPair;
|
|
26
|
+
exports.deriveKeyFromECDH = deriveKeyFromECDH;
|
|
27
|
+
exports.hmac = hmac;
|
|
28
|
+
exports.verifyHmac = verifyHmac;
|
|
29
|
+
exports.parsePublicKeyPem = parsePublicKeyPem;
|
|
30
|
+
exports.jwkToPublicKeyPem = jwkToPublicKeyPem;
|
|
31
|
+
exports.publicKeyPemToJwk = publicKeyPemToJwk;
|
|
32
|
+
exports.importPublicKey = importPublicKey;
|
|
33
|
+
exports.importPrivateKey = importPrivateKey;
|
|
34
|
+
exports.exportPublicKeyPem = exportPublicKeyPem;
|
|
35
|
+
exports.exportPrivateKeyPem = exportPrivateKeyPem;
|
|
36
|
+
exports.exportPublicKeyJwk = exportPublicKeyJwk;
|
|
37
|
+
exports.importSymmetricKey = importSymmetricKey;
|
|
38
|
+
exports.splitSymmetricKey = splitSymmetricKey;
|
|
39
|
+
exports.mergeSymmetricKeys = mergeSymmetricKeys;
|
|
25
40
|
const index_js_1 = require("../ciphers/index.js");
|
|
26
41
|
const binary_js_1 = require("../binary.js");
|
|
27
42
|
const declarations_js_1 = require("./declarations.js");
|
|
@@ -29,8 +44,12 @@ const errors_js_1 = require("../../../src/errors.js");
|
|
|
29
44
|
const crypto_utils_js_1 = require("./crypto-utils.js");
|
|
30
45
|
const hex_js_1 = require("../../../src/encodings/hex.js");
|
|
31
46
|
const base64_js_1 = require("../../../src/encodings/base64.js");
|
|
47
|
+
const jose_1 = require("jose");
|
|
48
|
+
const pemPublicToCrypto_js_1 = require("../../../src/crypto/pemPublicToCrypto.js");
|
|
49
|
+
const keysplit_js_1 = require("../utils/keysplit.js");
|
|
32
50
|
// Used to pass into native crypto functions
|
|
33
|
-
const
|
|
51
|
+
const ENC_DEC_METHODS = ['encrypt', 'decrypt'];
|
|
52
|
+
const SIGN_VERIFY_METHODS = ['sign', 'verify'];
|
|
34
53
|
exports.isSupported = typeof globalThis?.crypto !== 'undefined';
|
|
35
54
|
exports.method = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
|
|
36
55
|
exports.name = 'BrowserNativeCryptoService';
|
|
@@ -65,11 +84,93 @@ function rsaPkcs1Sha256(modulusLength = declarations_js_1.MIN_ASYMMETRIC_KEY_SIZ
|
|
|
65
84
|
};
|
|
66
85
|
}
|
|
67
86
|
/**
|
|
68
|
-
* Generate a random
|
|
69
|
-
* @
|
|
87
|
+
* Generate a random symmetric key (opaque).
|
|
88
|
+
* @param length - Key length in bytes (default 32 for AES-256)
|
|
89
|
+
* @return Opaque symmetric key
|
|
70
90
|
*/
|
|
71
91
|
async function generateKey(length) {
|
|
72
|
-
|
|
92
|
+
const keyBytes = await randomBytes(length || 32);
|
|
93
|
+
return wrapSymmetricKey(keyBytes);
|
|
94
|
+
}
|
|
95
|
+
// ============================================================
|
|
96
|
+
// Opaque Key Wrapping/Unwrapping Helpers
|
|
97
|
+
// ============================================================
|
|
98
|
+
/**
|
|
99
|
+
* Wrap a CryptoKey as an opaque PublicKey.
|
|
100
|
+
* @internal
|
|
101
|
+
*/
|
|
102
|
+
function wrapPublicKey(key, algorithm) {
|
|
103
|
+
const result = {
|
|
104
|
+
_brand: 'PublicKey',
|
|
105
|
+
algorithm,
|
|
106
|
+
_internal: key,
|
|
107
|
+
};
|
|
108
|
+
if (algorithm.startsWith('rsa:')) {
|
|
109
|
+
result.modulusBits = parseInt(algorithm.split(':')[1], 10);
|
|
110
|
+
}
|
|
111
|
+
else if (algorithm.startsWith('ec:')) {
|
|
112
|
+
const curvePart = algorithm.split(':')[1];
|
|
113
|
+
result.curve =
|
|
114
|
+
curvePart === 'secp256r1'
|
|
115
|
+
? 'P-256'
|
|
116
|
+
: curvePart === 'secp384r1'
|
|
117
|
+
? 'P-384'
|
|
118
|
+
: curvePart === 'secp521r1'
|
|
119
|
+
? 'P-521'
|
|
120
|
+
: undefined;
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Wrap a CryptoKey as an opaque PrivateKey.
|
|
126
|
+
* @internal
|
|
127
|
+
*/
|
|
128
|
+
function wrapPrivateKey(key, algorithm) {
|
|
129
|
+
const result = {
|
|
130
|
+
_brand: 'PrivateKey',
|
|
131
|
+
algorithm,
|
|
132
|
+
_internal: key,
|
|
133
|
+
};
|
|
134
|
+
if (algorithm.startsWith('rsa:')) {
|
|
135
|
+
result.modulusBits = parseInt(algorithm.split(':')[1], 10);
|
|
136
|
+
}
|
|
137
|
+
else if (algorithm.startsWith('ec:')) {
|
|
138
|
+
const curvePart = algorithm.split(':')[1];
|
|
139
|
+
result.curve =
|
|
140
|
+
curvePart === 'secp256r1'
|
|
141
|
+
? 'P-256'
|
|
142
|
+
: curvePart === 'secp384r1'
|
|
143
|
+
? 'P-384'
|
|
144
|
+
: curvePart === 'secp521r1'
|
|
145
|
+
? 'P-521'
|
|
146
|
+
: undefined;
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Unwrap an opaque key to get the internal CryptoKey.
|
|
152
|
+
* @internal
|
|
153
|
+
*/
|
|
154
|
+
function unwrapKey(key) {
|
|
155
|
+
return key._internal;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Wrap raw key bytes as an opaque SymmetricKey.
|
|
159
|
+
* @internal
|
|
160
|
+
*/
|
|
161
|
+
function wrapSymmetricKey(keyBytes) {
|
|
162
|
+
return {
|
|
163
|
+
_brand: 'SymmetricKey',
|
|
164
|
+
length: keyBytes.length * 8, // bits
|
|
165
|
+
_internal: keyBytes,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Unwrap an opaque SymmetricKey to get raw bytes.
|
|
170
|
+
* @internal
|
|
171
|
+
*/
|
|
172
|
+
function unwrapSymmetricKey(key) {
|
|
173
|
+
return key._internal;
|
|
73
174
|
}
|
|
74
175
|
/**
|
|
75
176
|
* Generate an RSA key pair
|
|
@@ -77,61 +178,60 @@ async function generateKey(length) {
|
|
|
77
178
|
* @param size in bits
|
|
78
179
|
*/
|
|
79
180
|
async function generateKeyPair(size) {
|
|
80
|
-
const
|
|
81
|
-
|
|
181
|
+
const keySize = size || declarations_js_1.MIN_ASYMMETRIC_KEY_SIZE_BITS;
|
|
182
|
+
const algoDomString = rsaOaepSha1(keySize);
|
|
183
|
+
const keyPair = await crypto.subtle.generateKey(algoDomString, true, ENC_DEC_METHODS);
|
|
184
|
+
// Map to supported algorithm sizes
|
|
185
|
+
let algorithm;
|
|
186
|
+
if (keySize === 2048) {
|
|
187
|
+
algorithm = 'rsa:2048';
|
|
188
|
+
}
|
|
189
|
+
else if (keySize === 4096) {
|
|
190
|
+
algorithm = 'rsa:4096';
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
throw new errors_js_1.ConfigurationError(`Unsupported RSA key size: ${keySize}. Only 2048 and 4096 are supported.`);
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
publicKey: wrapPublicKey(keyPair.publicKey, algorithm),
|
|
197
|
+
privateKey: wrapPrivateKey(keyPair.privateKey, algorithm),
|
|
198
|
+
};
|
|
82
199
|
}
|
|
83
200
|
/**
|
|
84
201
|
* Generate an RSA key pair suitable for signatures
|
|
85
202
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey}
|
|
86
203
|
*/
|
|
87
204
|
async function generateSigningKeyPair() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
modulusLength: 2048,
|
|
92
|
-
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
93
|
-
}, true, ['sign', 'verify']);
|
|
94
|
-
}
|
|
95
|
-
async function cryptoToPemPair(keysMaybe) {
|
|
96
|
-
const keys = keysMaybe;
|
|
97
|
-
if (!keys.privateKey || !keys.publicKey) {
|
|
98
|
-
// These are only ever generated here, so this should not happen
|
|
99
|
-
throw new Error('internal: invalid keys');
|
|
100
|
-
}
|
|
101
|
-
const [exPublic, exPrivate] = await Promise.all([
|
|
102
|
-
crypto.subtle.exportKey('spki', keys.publicKey),
|
|
103
|
-
crypto.subtle.exportKey('pkcs8', keys.privateKey),
|
|
104
|
-
]);
|
|
205
|
+
const rsaParams = rsaPkcs1Sha256(2048);
|
|
206
|
+
const keyPair = await crypto.subtle.generateKey(rsaParams, true, SIGN_VERIFY_METHODS);
|
|
207
|
+
const algorithm = 'rsa:2048';
|
|
105
208
|
return {
|
|
106
|
-
publicKey: (
|
|
107
|
-
privateKey: (
|
|
209
|
+
publicKey: wrapPublicKey(keyPair.publicKey, algorithm),
|
|
210
|
+
privateKey: wrapPrivateKey(keyPair.privateKey, algorithm),
|
|
108
211
|
};
|
|
109
212
|
}
|
|
110
213
|
/**
|
|
111
|
-
* Encrypt using a public key
|
|
112
|
-
*
|
|
113
|
-
* @param
|
|
214
|
+
* Encrypt using a public key (RSA-OAEP).
|
|
215
|
+
* Accepts Binary or SymmetricKey for key wrapping.
|
|
216
|
+
* @param payload Payload to encrypt (Binary) or symmetric key to wrap (SymmetricKey)
|
|
217
|
+
* @param publicKey Opaque public key
|
|
114
218
|
* @return Encrypted payload
|
|
115
219
|
*/
|
|
116
220
|
async function encryptWithPublicKey(payload, publicKey) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
221
|
+
let payloadBuffer;
|
|
222
|
+
// Handle SymmetricKey unwrapping
|
|
223
|
+
if ('_brand' in payload && payload._brand === 'SymmetricKey') {
|
|
224
|
+
// Pass Uint8Array directly — Web Crypto respects byteOffset/byteLength on typed array views.
|
|
225
|
+
payloadBuffer = unwrapSymmetricKey(payload);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// Binary payload
|
|
229
|
+
payloadBuffer = payload.asArrayBuffer();
|
|
230
|
+
}
|
|
231
|
+
const cryptoKey = unwrapKey(publicKey);
|
|
232
|
+
const result = await crypto.subtle.encrypt({ name: 'RSA-OAEP' }, cryptoKey, payloadBuffer);
|
|
127
233
|
return binary_js_1.Binary.fromArrayBuffer(result);
|
|
128
234
|
}
|
|
129
|
-
/**
|
|
130
|
-
* Generate a 16-byte initialization vector
|
|
131
|
-
*/
|
|
132
|
-
async function generateInitializationVector(length) {
|
|
133
|
-
return randomBytesAsHex(length || 16);
|
|
134
|
-
}
|
|
135
235
|
async function randomBytes(byteLength) {
|
|
136
236
|
const r = new Uint8Array(byteLength);
|
|
137
237
|
crypto.getRandomValues(r);
|
|
@@ -156,25 +256,20 @@ async function randomBytesAsHex(length) {
|
|
|
156
256
|
/**
|
|
157
257
|
* Decrypt a public-key encrypted payload with a private key
|
|
158
258
|
* @param encryptedPayload Payload to decrypt
|
|
159
|
-
* @param privateKey
|
|
259
|
+
* @param privateKey Opaque private key
|
|
160
260
|
* @return Decrypted payload
|
|
161
261
|
*/
|
|
162
262
|
async function decryptWithPrivateKey(encryptedPayload, privateKey) {
|
|
163
263
|
console.assert(typeof encryptedPayload === 'object', 'encryptedPayload must be object');
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
// Web Crypto APIs don't work with PEM formatted strings
|
|
167
|
-
const keyDataString = (0, crypto_utils_js_1.removePemFormatting)(privateKey);
|
|
168
|
-
const keyData = (0, base64_js_1.decodeArrayBuffer)(keyDataString);
|
|
169
|
-
const key = await crypto.subtle.importKey('pkcs8', keyData, algoDomString, false, ['decrypt']);
|
|
170
|
-
const payload = await crypto.subtle.decrypt({ name: 'RSA-OAEP' }, key, encryptedPayload.asArrayBuffer());
|
|
264
|
+
const cryptoKey = unwrapKey(privateKey);
|
|
265
|
+
const payload = await crypto.subtle.decrypt({ name: 'RSA-OAEP' }, cryptoKey, encryptedPayload.asArrayBuffer());
|
|
171
266
|
const bufferView = new Uint8Array(payload);
|
|
172
267
|
return binary_js_1.Binary.fromArrayBuffer(bufferView.buffer);
|
|
173
268
|
}
|
|
174
269
|
/**
|
|
175
270
|
* Decrypt content synchronously
|
|
176
271
|
* @param payload The payload to decrypt
|
|
177
|
-
* @param key The encryption key
|
|
272
|
+
* @param key The symmetric encryption key (opaque)
|
|
178
273
|
* @param iv The initialization vector
|
|
179
274
|
* @param algorithm The algorithm to use for encryption
|
|
180
275
|
* @param authTag The authentication tag for authenticated crypto.
|
|
@@ -196,9 +291,20 @@ async function _doEncrypt(payload, key, iv, algorithm) {
|
|
|
196
291
|
console.assert(payload != null);
|
|
197
292
|
console.assert(key != null);
|
|
198
293
|
console.assert(iv != null);
|
|
199
|
-
|
|
294
|
+
// Handle both Binary and SymmetricKey payloads
|
|
295
|
+
let payloadBuffer;
|
|
296
|
+
if ('_brand' in payload && payload._brand === 'SymmetricKey') {
|
|
297
|
+
// Pass Uint8Array directly — Web Crypto respects byteOffset/byteLength on typed array views.
|
|
298
|
+
payloadBuffer = unwrapSymmetricKey(payload);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
// Binary payload
|
|
302
|
+
payloadBuffer = payload.asArrayBuffer();
|
|
303
|
+
}
|
|
200
304
|
const algoDomString = getSymmetricAlgoDomString(iv, algorithm);
|
|
201
|
-
|
|
305
|
+
// Unwrap symmetric key to get raw bytes
|
|
306
|
+
const keyBytes = unwrapSymmetricKey(key);
|
|
307
|
+
const importedKey = await _importKey(keyBytes, algoDomString);
|
|
202
308
|
const encrypted = await crypto.subtle.encrypt(algoDomString, importedKey, payloadBuffer);
|
|
203
309
|
if (algoDomString.name === 'AES-GCM') {
|
|
204
310
|
return {
|
|
@@ -224,7 +330,9 @@ async function _doDecrypt(payload, key, iv, algorithm, authTag) {
|
|
|
224
330
|
payloadBuffer = gcmPayload.buffer;
|
|
225
331
|
}
|
|
226
332
|
const algoDomString = getSymmetricAlgoDomString(iv, algorithm);
|
|
227
|
-
|
|
333
|
+
// Unwrap symmetric key to get raw bytes
|
|
334
|
+
const keyBytes = unwrapSymmetricKey(key);
|
|
335
|
+
const importedKey = await _importKey(keyBytes, algoDomString);
|
|
228
336
|
algoDomString.iv = iv.asArrayBuffer();
|
|
229
337
|
const decrypted = await crypto.subtle
|
|
230
338
|
.decrypt(algoDomString, importedKey, payloadBuffer)
|
|
@@ -237,8 +345,8 @@ async function _doDecrypt(payload, key, iv, algorithm, authTag) {
|
|
|
237
345
|
});
|
|
238
346
|
return { payload: binary_js_1.Binary.fromArrayBuffer(decrypted) };
|
|
239
347
|
}
|
|
240
|
-
function _importKey(
|
|
241
|
-
return crypto.subtle.importKey('raw',
|
|
348
|
+
function _importKey(keyBytes, algorithm) {
|
|
349
|
+
return crypto.subtle.importKey('raw', keyBytes, algorithm, true, ENC_DEC_METHODS);
|
|
242
350
|
}
|
|
243
351
|
/**
|
|
244
352
|
* Get a DOMString representing the algorithm to use for a crypto
|
|
@@ -262,27 +370,6 @@ function getSymmetricAlgoDomString(iv, algorithm) {
|
|
|
262
370
|
* @param content String content
|
|
263
371
|
* @return Hex hash
|
|
264
372
|
*/
|
|
265
|
-
async function sha256(content) {
|
|
266
|
-
const buffer = new TextEncoder().encode(content);
|
|
267
|
-
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
|
|
268
|
-
return (0, hex_js_1.encodeArrayBuffer)(hashBuffer);
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Create an HMAC SHA256 hash
|
|
272
|
-
* @param key Key string
|
|
273
|
-
* @param content Content string
|
|
274
|
-
* @return Hex hash
|
|
275
|
-
*/
|
|
276
|
-
async function hmac(key, content) {
|
|
277
|
-
const contentBuffer = new TextEncoder().encode(content);
|
|
278
|
-
const keyBuffer = hex2Ab(key);
|
|
279
|
-
const cryptoKey = await crypto.subtle.importKey('raw', keyBuffer, {
|
|
280
|
-
name: 'HMAC',
|
|
281
|
-
hash: { name: 'SHA-256' },
|
|
282
|
-
}, true, ['sign', 'verify']);
|
|
283
|
-
const hashBuffer = await crypto.subtle.sign('HMAC', cryptoKey, contentBuffer);
|
|
284
|
-
return (0, hex_js_1.encodeArrayBuffer)(hashBuffer);
|
|
285
|
-
}
|
|
286
373
|
/**
|
|
287
374
|
* Create an ArrayBuffer from a hex string.
|
|
288
375
|
* https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String?hl=en
|
|
@@ -296,20 +383,694 @@ function hex2Ab(hex) {
|
|
|
296
383
|
}
|
|
297
384
|
return buffer;
|
|
298
385
|
}
|
|
386
|
+
/**
|
|
387
|
+
* Get the Web Crypto algorithm parameters for a signing algorithm.
|
|
388
|
+
*/
|
|
389
|
+
function getSigningAlgorithmParams(algorithm) {
|
|
390
|
+
switch (algorithm) {
|
|
391
|
+
case 'RS256':
|
|
392
|
+
return {
|
|
393
|
+
importParams: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },
|
|
394
|
+
signParams: 'RSASSA-PKCS1-v1_5',
|
|
395
|
+
};
|
|
396
|
+
case 'ES256':
|
|
397
|
+
return {
|
|
398
|
+
importParams: { name: 'ECDSA', namedCurve: 'P-256' },
|
|
399
|
+
signParams: { name: 'ECDSA', hash: 'SHA-256' },
|
|
400
|
+
};
|
|
401
|
+
case 'ES384':
|
|
402
|
+
return {
|
|
403
|
+
importParams: { name: 'ECDSA', namedCurve: 'P-384' },
|
|
404
|
+
signParams: { name: 'ECDSA', hash: 'SHA-384' },
|
|
405
|
+
};
|
|
406
|
+
case 'ES512':
|
|
407
|
+
return {
|
|
408
|
+
importParams: { name: 'ECDSA', namedCurve: 'P-521' },
|
|
409
|
+
signParams: { name: 'ECDSA', hash: 'SHA-512' },
|
|
410
|
+
};
|
|
411
|
+
default:
|
|
412
|
+
throw new errors_js_1.ConfigurationError(`Unsupported signing algorithm: ${algorithm}`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Convert IEEE P1363 signature format (used by WebCrypto ECDSA) to DER format (used by JWT).
|
|
417
|
+
* RS256 signatures don't need conversion.
|
|
418
|
+
*/
|
|
419
|
+
function ieeeP1363ToDer(signature, algorithm) {
|
|
420
|
+
if (algorithm === 'RS256') {
|
|
421
|
+
return signature;
|
|
422
|
+
}
|
|
423
|
+
// IEEE P1363: r || s where each is padded to key size
|
|
424
|
+
const halfLen = signature.length / 2;
|
|
425
|
+
const r = signature.slice(0, halfLen);
|
|
426
|
+
const s = signature.slice(halfLen);
|
|
427
|
+
// Remove leading zeros but keep one if the high bit is set
|
|
428
|
+
const trimLeadingZeros = (arr) => {
|
|
429
|
+
let i = 0;
|
|
430
|
+
while (i < arr.length - 1 && arr[i] === 0)
|
|
431
|
+
i++;
|
|
432
|
+
return arr.slice(i);
|
|
433
|
+
};
|
|
434
|
+
let rTrimmed = trimLeadingZeros(r);
|
|
435
|
+
let sTrimmed = trimLeadingZeros(s);
|
|
436
|
+
// Add leading zero if high bit is set (to keep positive in DER)
|
|
437
|
+
if (rTrimmed[0] & 0x80) {
|
|
438
|
+
const padded = new Uint8Array(rTrimmed.length + 1);
|
|
439
|
+
padded.set(rTrimmed, 1);
|
|
440
|
+
rTrimmed = padded;
|
|
441
|
+
}
|
|
442
|
+
if (sTrimmed[0] & 0x80) {
|
|
443
|
+
const padded = new Uint8Array(sTrimmed.length + 1);
|
|
444
|
+
padded.set(sTrimmed, 1);
|
|
445
|
+
sTrimmed = padded;
|
|
446
|
+
}
|
|
447
|
+
// DER SEQUENCE: 0x30 [length] [r INTEGER] [s INTEGER]
|
|
448
|
+
// INTEGER: 0x02 [length] [value]
|
|
449
|
+
const rDer = new Uint8Array([0x02, rTrimmed.length, ...rTrimmed]);
|
|
450
|
+
const sDer = new Uint8Array([0x02, sTrimmed.length, ...sTrimmed]);
|
|
451
|
+
const seqLen = rDer.length + sDer.length;
|
|
452
|
+
// DER length: short-form for < 128, long-form (0x81 nn) for 128-255.
|
|
453
|
+
// ECDSA sequences never exceed 255 bytes for any supported curve.
|
|
454
|
+
const lenBytes = seqLen < 128 ? new Uint8Array([seqLen]) : new Uint8Array([0x81, seqLen]);
|
|
455
|
+
const result = new Uint8Array(1 + lenBytes.length + seqLen);
|
|
456
|
+
result[0] = 0x30;
|
|
457
|
+
result.set(lenBytes, 1);
|
|
458
|
+
result.set(rDer, 1 + lenBytes.length);
|
|
459
|
+
result.set(sDer, 1 + lenBytes.length + rDer.length);
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Convert DER signature format (used by JWT) to IEEE P1363 format (used by WebCrypto ECDSA).
|
|
464
|
+
* RS256 signatures don't need conversion.
|
|
465
|
+
*/
|
|
466
|
+
function derToIeeeP1363(signature, algorithm) {
|
|
467
|
+
if (algorithm === 'RS256') {
|
|
468
|
+
return signature;
|
|
469
|
+
}
|
|
470
|
+
// Determine the expected component length based on algorithm
|
|
471
|
+
let componentLen;
|
|
472
|
+
switch (algorithm) {
|
|
473
|
+
case 'ES256':
|
|
474
|
+
componentLen = 32;
|
|
475
|
+
break;
|
|
476
|
+
case 'ES384':
|
|
477
|
+
componentLen = 48;
|
|
478
|
+
break;
|
|
479
|
+
case 'ES512':
|
|
480
|
+
componentLen = 66;
|
|
481
|
+
break;
|
|
482
|
+
default:
|
|
483
|
+
throw new errors_js_1.ConfigurationError(`Unsupported algorithm for DER conversion: ${algorithm}`);
|
|
484
|
+
}
|
|
485
|
+
// Parse DER: SEQUENCE { INTEGER r, INTEGER s }
|
|
486
|
+
if (signature[0] !== 0x30) {
|
|
487
|
+
throw new errors_js_1.ConfigurationError('Invalid DER signature: expected SEQUENCE');
|
|
488
|
+
}
|
|
489
|
+
// Skip SEQUENCE tag, then parse DER length (short- or long-form).
|
|
490
|
+
let offset = 1;
|
|
491
|
+
if (signature[offset] & 0x80) {
|
|
492
|
+
// Long-form: low 7 bits = number of subsequent length bytes.
|
|
493
|
+
const lenBytesCount = signature[offset] & 0x7f;
|
|
494
|
+
if (lenBytesCount === 0 || lenBytesCount > 4) {
|
|
495
|
+
throw new errors_js_1.ConfigurationError('Invalid DER signature: invalid long-form length');
|
|
496
|
+
}
|
|
497
|
+
offset += 1 + lenBytesCount;
|
|
498
|
+
if (offset > signature.length) {
|
|
499
|
+
throw new errors_js_1.ConfigurationError('Invalid DER signature: length bytes exceed signature length');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
// Short-form: single length byte.
|
|
504
|
+
offset += 1;
|
|
505
|
+
}
|
|
506
|
+
// Parse r INTEGER
|
|
507
|
+
if (signature[offset] !== 0x02) {
|
|
508
|
+
throw new errors_js_1.ConfigurationError('Invalid DER signature: expected INTEGER for r');
|
|
509
|
+
}
|
|
510
|
+
const rLen = signature[offset + 1];
|
|
511
|
+
offset += 2;
|
|
512
|
+
let r = signature.slice(offset, offset + rLen);
|
|
513
|
+
offset += rLen;
|
|
514
|
+
// Parse s INTEGER
|
|
515
|
+
if (signature[offset] !== 0x02) {
|
|
516
|
+
throw new errors_js_1.ConfigurationError('Invalid DER signature: expected INTEGER for s');
|
|
517
|
+
}
|
|
518
|
+
const sLen = signature[offset + 1];
|
|
519
|
+
offset += 2;
|
|
520
|
+
let s = signature.slice(offset, offset + sLen);
|
|
521
|
+
// Remove leading zero padding if present
|
|
522
|
+
if (r[0] === 0 && r.length > componentLen) {
|
|
523
|
+
r = r.slice(1);
|
|
524
|
+
}
|
|
525
|
+
if (s[0] === 0 && s.length > componentLen) {
|
|
526
|
+
s = s.slice(1);
|
|
527
|
+
}
|
|
528
|
+
// Pad to component length
|
|
529
|
+
const result = new Uint8Array(componentLen * 2);
|
|
530
|
+
result.set(r, componentLen - r.length);
|
|
531
|
+
result.set(s, componentLen * 2 - s.length);
|
|
532
|
+
return result;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Sign data with an asymmetric private key.
|
|
536
|
+
*/
|
|
537
|
+
async function sign(data, privateKey, algorithm) {
|
|
538
|
+
const { signParams } = getSigningAlgorithmParams(algorithm);
|
|
539
|
+
// Unwrap the internal CryptoKey
|
|
540
|
+
const key = unwrapKey(privateKey);
|
|
541
|
+
// Sign the data
|
|
542
|
+
const signature = await crypto.subtle.sign(signParams, key, data);
|
|
543
|
+
// Convert from IEEE P1363 to DER for EC algorithms
|
|
544
|
+
return ieeeP1363ToDer(new Uint8Array(signature), algorithm);
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Verify signature with an asymmetric public key.
|
|
548
|
+
*/
|
|
549
|
+
async function verify(data, signature, publicKey, algorithm) {
|
|
550
|
+
const { signParams } = getSigningAlgorithmParams(algorithm);
|
|
551
|
+
// Unwrap the internal CryptoKey
|
|
552
|
+
const key = unwrapKey(publicKey);
|
|
553
|
+
// Convert from DER to IEEE P1363 for EC algorithms
|
|
554
|
+
const ieeeSignature = derToIeeeP1363(signature, algorithm);
|
|
555
|
+
// Verify the signature
|
|
556
|
+
return crypto.subtle.verify(signParams, key, ieeeSignature, data);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Compute hash digest.
|
|
560
|
+
*/
|
|
561
|
+
async function digest(algorithm, data) {
|
|
562
|
+
// Validate algorithm and map to Web Crypto name
|
|
563
|
+
const validAlgorithms = ['SHA-256', 'SHA-384', 'SHA-512'];
|
|
564
|
+
if (!validAlgorithms.includes(algorithm)) {
|
|
565
|
+
throw new errors_js_1.ConfigurationError(`Unsupported hash algorithm: ${algorithm}`);
|
|
566
|
+
}
|
|
567
|
+
const hashBuffer = await crypto.subtle.digest(algorithm, data);
|
|
568
|
+
return new Uint8Array(hashBuffer);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Extract PEM public key from X.509 certificate or return PEM key as-is.
|
|
572
|
+
*
|
|
573
|
+
* @param certOrPem - A PEM-encoded X.509 certificate or public key
|
|
574
|
+
* @param jwaAlgorithm - JWA algorithm hint for certificate parsing (RS256, RS512, ES256, ES384, ES512).
|
|
575
|
+
* If not provided for a certificate, will attempt to auto-detect from OIDs.
|
|
576
|
+
*/
|
|
577
|
+
async function extractPublicKeyPem(certOrPem, jwaAlgorithm) {
|
|
578
|
+
// If it's a certificate, extract the public key
|
|
579
|
+
if (certOrPem.includes('-----BEGIN CERTIFICATE-----')) {
|
|
580
|
+
let alg = jwaAlgorithm;
|
|
581
|
+
if (!alg) {
|
|
582
|
+
// Auto-detect algorithm from certificate OIDs
|
|
583
|
+
const certBody = certOrPem.replace(/-----(BEGIN|END) CERTIFICATE-----|\s/g, '');
|
|
584
|
+
const certBytes = (0, base64_js_1.decodeArrayBuffer)(certBody);
|
|
585
|
+
const hex = (0, hex_js_1.encodeArrayBuffer)(certBytes);
|
|
586
|
+
alg = (0, pemPublicToCrypto_js_1.toJwsAlg)(hex);
|
|
587
|
+
}
|
|
588
|
+
const cert = await (0, jose_1.importX509)(certOrPem, alg, { extractable: true });
|
|
589
|
+
return (0, jose_1.exportSPKI)(cert);
|
|
590
|
+
}
|
|
591
|
+
// If it's already a PEM public key, return as-is
|
|
592
|
+
if (certOrPem.includes('-----BEGIN PUBLIC KEY-----')) {
|
|
593
|
+
return certOrPem;
|
|
594
|
+
}
|
|
595
|
+
throw new errors_js_1.ConfigurationError('Input must be a PEM-encoded certificate or public key');
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Map ECCurve to Web Crypto named curve.
|
|
599
|
+
*/
|
|
600
|
+
function curveToNamedCurve(curve) {
|
|
601
|
+
switch (curve) {
|
|
602
|
+
case 'P-256':
|
|
603
|
+
return 'P-256';
|
|
604
|
+
case 'P-384':
|
|
605
|
+
return 'P-384';
|
|
606
|
+
case 'P-521':
|
|
607
|
+
return 'P-521';
|
|
608
|
+
default:
|
|
609
|
+
throw new errors_js_1.ConfigurationError(`Unsupported curve: ${curve}`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Generate an EC key pair for ECDH key agreement.
|
|
614
|
+
*/
|
|
615
|
+
async function generateECKeyPair(curve = 'P-256') {
|
|
616
|
+
const namedCurve = curveToNamedCurve(curve);
|
|
617
|
+
// Generate key pair for ECDH key agreement
|
|
618
|
+
const keyPair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve }, true, [
|
|
619
|
+
'deriveBits',
|
|
620
|
+
]);
|
|
621
|
+
// Map to KeyAlgorithm literal type
|
|
622
|
+
let algorithm;
|
|
623
|
+
switch (namedCurve) {
|
|
624
|
+
case 'P-256':
|
|
625
|
+
algorithm = 'ec:secp256r1';
|
|
626
|
+
break;
|
|
627
|
+
case 'P-384':
|
|
628
|
+
algorithm = 'ec:secp384r1';
|
|
629
|
+
break;
|
|
630
|
+
case 'P-521':
|
|
631
|
+
algorithm = 'ec:secp521r1';
|
|
632
|
+
break;
|
|
633
|
+
default:
|
|
634
|
+
throw new errors_js_1.ConfigurationError(`Unsupported curve: ${namedCurve}`);
|
|
635
|
+
}
|
|
636
|
+
return {
|
|
637
|
+
publicKey: wrapPublicKey(keyPair.publicKey, algorithm),
|
|
638
|
+
privateKey: wrapPrivateKey(keyPair.privateKey, algorithm),
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Supported EC curves.
|
|
643
|
+
*/
|
|
644
|
+
const SUPPORTED_EC_CURVES = ['P-256', 'P-384', 'P-521'];
|
|
645
|
+
/**
|
|
646
|
+
* Decode base64url string and return byte length.
|
|
647
|
+
* Uses the existing base64 decoder which handles both standard and URL-safe encoding.
|
|
648
|
+
*/
|
|
649
|
+
function base64urlByteLength(base64url) {
|
|
650
|
+
// Add padding if needed (base64url omits padding)
|
|
651
|
+
const padding = (4 - (base64url.length % 4)) % 4;
|
|
652
|
+
const padded = base64url + '='.repeat(padding);
|
|
653
|
+
return (0, base64_js_1.decodeArrayBuffer)(padded).byteLength;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Extract EC curve from a public key by parsing ASN.1 OIDs.
|
|
657
|
+
* Reuses the existing guessCurveName function that checks for curve OIDs.
|
|
658
|
+
*/
|
|
659
|
+
function extractEcCurveFromPublicKey(keyData) {
|
|
660
|
+
// Convert to hex for OID parsing
|
|
661
|
+
const hexKey = (0, hex_js_1.encodeArrayBuffer)(keyData);
|
|
662
|
+
// Use existing OID parser (returns 'P-256', 'P-384', or 'P-521')
|
|
663
|
+
const curveName = (0, pemPublicToCrypto_js_1.guessCurveName)(hexKey);
|
|
664
|
+
return curveName;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Perform ECDH key agreement followed by HKDF key derivation.
|
|
668
|
+
* Returns opaque symmetric key for symmetric encryption.
|
|
669
|
+
*/
|
|
670
|
+
async function deriveKeyFromECDH(privateKey, publicKey, hkdfParams) {
|
|
671
|
+
// Unwrap the internal CryptoKeys
|
|
672
|
+
const privateKeyCrypto = unwrapKey(privateKey);
|
|
673
|
+
const publicKeyCrypto = unwrapKey(publicKey);
|
|
674
|
+
// Get curve from key metadata
|
|
675
|
+
const curve = publicKey.curve;
|
|
676
|
+
if (!curve) {
|
|
677
|
+
throw new errors_js_1.ConfigurationError('EC curve not found on public key');
|
|
678
|
+
}
|
|
679
|
+
// Determine bits based on curve
|
|
680
|
+
const curveBits = {
|
|
681
|
+
'P-256': 256,
|
|
682
|
+
'P-384': 384,
|
|
683
|
+
'P-521': 528, // P-521 derives 528 bits (66 bytes)
|
|
684
|
+
};
|
|
685
|
+
const bits = curveBits[curve];
|
|
686
|
+
// Perform ECDH to get shared secret
|
|
687
|
+
const sharedSecret = await crypto.subtle.deriveBits({ name: 'ECDH', public: publicKeyCrypto }, privateKeyCrypto, bits);
|
|
688
|
+
// Import shared secret as HKDF key material
|
|
689
|
+
const hkdfKey = await crypto.subtle.importKey('raw', sharedSecret, 'HKDF', false, ['deriveKey']);
|
|
690
|
+
// Derive the final key using HKDF
|
|
691
|
+
const keyLength = hkdfParams.keyLength ?? 256;
|
|
692
|
+
const derivedKey = await crypto.subtle.deriveKey({
|
|
693
|
+
name: 'HKDF',
|
|
694
|
+
hash: hkdfParams.hash,
|
|
695
|
+
salt: hkdfParams.salt,
|
|
696
|
+
info: hkdfParams.info ?? new Uint8Array(0),
|
|
697
|
+
}, hkdfKey, { name: 'AES-GCM', length: keyLength }, true, ['encrypt', 'decrypt']);
|
|
698
|
+
// Export the derived key as raw bytes and wrap as SymmetricKey
|
|
699
|
+
const keyBytes = await crypto.subtle.exportKey('raw', derivedKey);
|
|
700
|
+
return wrapSymmetricKey(new Uint8Array(keyBytes));
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Compute HMAC-SHA256 of data with a symmetric key.
|
|
704
|
+
*/
|
|
705
|
+
async function hmac(data, key) {
|
|
706
|
+
// Unwrap symmetric key to get raw bytes
|
|
707
|
+
const keyBytes = unwrapSymmetricKey(key);
|
|
708
|
+
const cryptoKey = await crypto.subtle.importKey('raw', keyBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
709
|
+
const signature = await crypto.subtle.sign('HMAC', cryptoKey, data);
|
|
710
|
+
return new Uint8Array(signature);
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Verify HMAC-SHA256. Standalone utility — not part of CryptoService interface.
|
|
714
|
+
*/
|
|
715
|
+
async function verifyHmac(data, signature, key) {
|
|
716
|
+
const keyBytes = unwrapSymmetricKey(key);
|
|
717
|
+
const cryptoKey = await crypto.subtle.importKey('raw', keyBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']);
|
|
718
|
+
return crypto.subtle.verify('HMAC', cryptoKey, signature, data);
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Extract RSA modulus bit length by importing key and exporting as JWK.
|
|
722
|
+
* Uses Web Crypto's built-in ASN.1 parsing for robustness.
|
|
723
|
+
*/
|
|
724
|
+
async function extractRsaModulusBitLength(keyData) {
|
|
725
|
+
const key = await crypto.subtle.importKey('spki', keyData, { name: 'RSA-OAEP', hash: 'SHA-256' }, true, // extractable
|
|
726
|
+
['encrypt']);
|
|
727
|
+
const jwk = await crypto.subtle.exportKey('jwk', key);
|
|
728
|
+
if (!jwk.n) {
|
|
729
|
+
throw new errors_js_1.ConfigurationError('Invalid RSA key: missing modulus');
|
|
730
|
+
}
|
|
731
|
+
// JWK 'n' is base64url-encoded modulus
|
|
732
|
+
// Decode and count bytes, multiply by 8 for bits
|
|
733
|
+
return base64urlByteLength(jwk.n) * 8;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Import and validate a PEM public key, returning algorithm info.
|
|
737
|
+
* Uses JWK export for robust key parameter detection.
|
|
738
|
+
*/
|
|
739
|
+
async function parsePublicKeyPem(pem) {
|
|
740
|
+
// First extract public key if it's a certificate
|
|
741
|
+
let publicKeyPem = pem;
|
|
742
|
+
if (pem.includes('-----BEGIN CERTIFICATE-----')) {
|
|
743
|
+
publicKeyPem = await extractPublicKeyPem(pem);
|
|
744
|
+
}
|
|
745
|
+
if (!publicKeyPem.includes('-----BEGIN PUBLIC KEY-----')) {
|
|
746
|
+
throw new errors_js_1.ConfigurationError('Input must be a PEM-encoded public key or certificate');
|
|
747
|
+
}
|
|
748
|
+
const keyData = (0, base64_js_1.decodeArrayBuffer)((0, crypto_utils_js_1.removePemFormatting)(publicKeyPem));
|
|
749
|
+
// Try RSA first - use JWK export to get modulus size
|
|
750
|
+
try {
|
|
751
|
+
const modulusBits = await extractRsaModulusBitLength(keyData);
|
|
752
|
+
let algorithm;
|
|
753
|
+
if (modulusBits < declarations_js_1.MIN_ASYMMETRIC_KEY_SIZE_BITS) {
|
|
754
|
+
throw new errors_js_1.ConfigurationError(`RSA key size ${modulusBits} bits is below the minimum of ${declarations_js_1.MIN_ASYMMETRIC_KEY_SIZE_BITS} bits`);
|
|
755
|
+
}
|
|
756
|
+
else if (modulusBits <= 2048) {
|
|
757
|
+
algorithm = 'rsa:2048';
|
|
758
|
+
}
|
|
759
|
+
else if (modulusBits <= 4096) {
|
|
760
|
+
algorithm = 'rsa:4096';
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
throw new errors_js_1.ConfigurationError(`Unsupported RSA key size: ${modulusBits} bits`);
|
|
764
|
+
}
|
|
765
|
+
return { algorithm, pem: publicKeyPem };
|
|
766
|
+
}
|
|
767
|
+
catch (e) {
|
|
768
|
+
// If it's our own ConfigurationError, rethrow
|
|
769
|
+
if (e instanceof errors_js_1.ConfigurationError) {
|
|
770
|
+
throw e;
|
|
771
|
+
}
|
|
772
|
+
// Not an RSA key, try EC next
|
|
773
|
+
}
|
|
774
|
+
// Try EC - parse curve from OID
|
|
775
|
+
try {
|
|
776
|
+
const detectedCurve = extractEcCurveFromPublicKey(keyData);
|
|
777
|
+
const curveMap = {
|
|
778
|
+
'P-256': 'ec:secp256r1',
|
|
779
|
+
'P-384': 'ec:secp384r1',
|
|
780
|
+
'P-521': 'ec:secp521r1',
|
|
781
|
+
};
|
|
782
|
+
return { algorithm: curveMap[detectedCurve], pem: publicKeyPem };
|
|
783
|
+
}
|
|
784
|
+
catch {
|
|
785
|
+
// Not a valid EC key
|
|
786
|
+
}
|
|
787
|
+
throw new errors_js_1.ConfigurationError('Unable to determine public key algorithm - unsupported key type');
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Convert a JWK (JSON Web Key) to PEM format.
|
|
791
|
+
*/
|
|
792
|
+
async function jwkToPublicKeyPem(jwk) {
|
|
793
|
+
let key;
|
|
794
|
+
if (jwk.kty === 'RSA') {
|
|
795
|
+
// RSA key
|
|
796
|
+
key = await crypto.subtle.importKey('jwk', jwk, { name: 'RSA-OAEP', hash: 'SHA-256' }, true, [
|
|
797
|
+
'encrypt',
|
|
798
|
+
]);
|
|
799
|
+
}
|
|
800
|
+
else if (jwk.kty === 'EC') {
|
|
801
|
+
// EC key
|
|
802
|
+
const crv = jwk.crv;
|
|
803
|
+
if (!crv || !['P-256', 'P-384', 'P-521'].includes(crv)) {
|
|
804
|
+
throw new errors_js_1.ConfigurationError(`Unsupported EC curve: ${crv}`);
|
|
805
|
+
}
|
|
806
|
+
key = await crypto.subtle.importKey('jwk', jwk, { name: 'ECDH', namedCurve: crv }, true, []);
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
throw new errors_js_1.ConfigurationError(`Unsupported JWK key type: ${jwk.kty}`);
|
|
810
|
+
}
|
|
811
|
+
const spkiBuffer = await crypto.subtle.exportKey('spki', key);
|
|
812
|
+
return (0, crypto_utils_js_1.formatAsPem)(spkiBuffer, 'PUBLIC KEY');
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Convert a PEM public key to JWK format.
|
|
816
|
+
* Returns only public key components (no private key data).
|
|
817
|
+
*/
|
|
818
|
+
async function publicKeyPemToJwk(publicKeyPem) {
|
|
819
|
+
const keyDataBase64 = (0, crypto_utils_js_1.removePemFormatting)(publicKeyPem);
|
|
820
|
+
const keyBuffer = (0, base64_js_1.decodeArrayBuffer)(keyDataBase64);
|
|
821
|
+
const hex = (0, hex_js_1.encodeArrayBuffer)(keyBuffer);
|
|
822
|
+
// Detect key type using OID
|
|
823
|
+
const algorithmName = (0, pemPublicToCrypto_js_1.guessAlgorithmName)(hex);
|
|
824
|
+
if (algorithmName === 'ECDH' || algorithmName === 'ECDSA') {
|
|
825
|
+
// EC key - detect curve from OID
|
|
826
|
+
const namedCurve = (0, pemPublicToCrypto_js_1.guessCurveName)(hex);
|
|
827
|
+
const key = await crypto.subtle.importKey('spki', keyBuffer, { name: 'ECDSA', namedCurve }, true, ['verify']);
|
|
828
|
+
const jwk = await crypto.subtle.exportKey('jwk', key);
|
|
829
|
+
// Return only public key components
|
|
830
|
+
const { kty, crv, x, y } = jwk;
|
|
831
|
+
return { kty, crv, x, y };
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
// RSA key
|
|
835
|
+
const key = await crypto.subtle.importKey('spki', keyBuffer, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, true, ['verify']);
|
|
836
|
+
const jwk = await crypto.subtle.exportKey('jwk', key);
|
|
837
|
+
// Return only public key components
|
|
838
|
+
const { kty, e, n } = jwk;
|
|
839
|
+
return { kty, e, n };
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
// ============================================================
|
|
843
|
+
// Key Import Functions (PEM → Opaque)
|
|
844
|
+
// ============================================================
|
|
845
|
+
/**
|
|
846
|
+
* Import a PEM public key as an opaque key.
|
|
847
|
+
*/
|
|
848
|
+
async function importPublicKey(pem, options) {
|
|
849
|
+
const { usage = 'encrypt', extractable = true, algorithmHint } = options;
|
|
850
|
+
// Detect algorithm from PEM; also normalises certificates → plain SPKI PEM.
|
|
851
|
+
const keyInfo = await parsePublicKeyPem(pem);
|
|
852
|
+
const algorithm = algorithmHint || keyInfo.algorithm;
|
|
853
|
+
// Use keyInfo.pem (normalised SPKI) not the original pem, which may be a certificate.
|
|
854
|
+
// Passing raw X.509 DER bytes to crypto.subtle.importKey('spki') would throw DataError.
|
|
855
|
+
const keyData = (0, crypto_utils_js_1.removePemFormatting)(keyInfo.pem);
|
|
856
|
+
const keyBuffer = (0, base64_js_1.decodeArrayBuffer)(keyData);
|
|
857
|
+
// Determine Web Crypto algorithm and usages based on key type and usage
|
|
858
|
+
let cryptoAlgorithm;
|
|
859
|
+
let keyUsages;
|
|
860
|
+
if (algorithm.startsWith('rsa:')) {
|
|
861
|
+
if (usage === 'encrypt') {
|
|
862
|
+
cryptoAlgorithm = rsaOaepSha1();
|
|
863
|
+
keyUsages = ['encrypt'];
|
|
864
|
+
}
|
|
865
|
+
else if (usage === 'sign') {
|
|
866
|
+
cryptoAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };
|
|
867
|
+
keyUsages = ['verify'];
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
throw new errors_js_1.ConfigurationError('RSA keys only support usage: encrypt or sign');
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
else if (algorithm.startsWith('ec:')) {
|
|
874
|
+
const curve = algorithm.split(':')[1];
|
|
875
|
+
const namedCurve = curve === 'secp256r1'
|
|
876
|
+
? 'P-256'
|
|
877
|
+
: curve === 'secp384r1'
|
|
878
|
+
? 'P-384'
|
|
879
|
+
: curve === 'secp521r1'
|
|
880
|
+
? 'P-521'
|
|
881
|
+
: (() => {
|
|
882
|
+
throw new errors_js_1.ConfigurationError(`Unsupported EC curve: ${curve}`);
|
|
883
|
+
})();
|
|
884
|
+
if (usage === 'derive') {
|
|
885
|
+
cryptoAlgorithm = { name: 'ECDH', namedCurve };
|
|
886
|
+
keyUsages = [];
|
|
887
|
+
}
|
|
888
|
+
else if (usage === 'sign') {
|
|
889
|
+
cryptoAlgorithm = { name: 'ECDSA', namedCurve };
|
|
890
|
+
keyUsages = ['verify'];
|
|
891
|
+
}
|
|
892
|
+
else {
|
|
893
|
+
throw new errors_js_1.ConfigurationError('EC keys only support usage: derive or sign');
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
else {
|
|
897
|
+
throw new errors_js_1.ConfigurationError(`Unsupported algorithm: ${algorithm}`);
|
|
898
|
+
}
|
|
899
|
+
// Import as CryptoKey
|
|
900
|
+
const cryptoKey = await crypto.subtle.importKey('spki', keyBuffer, cryptoAlgorithm, extractable, keyUsages);
|
|
901
|
+
return wrapPublicKey(cryptoKey, algorithm);
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Import a PEM private key as an opaque key.
|
|
905
|
+
*/
|
|
906
|
+
async function importPrivateKey(pem, options) {
|
|
907
|
+
const { usage = 'encrypt', extractable = true, algorithmHint } = options;
|
|
908
|
+
// Detect algorithm from PEM structure (similar to public key detection)
|
|
909
|
+
// For now, use algorithmHint if provided, otherwise detect from key structure
|
|
910
|
+
let algorithm;
|
|
911
|
+
const keyData = (0, crypto_utils_js_1.removePemFormatting)(pem);
|
|
912
|
+
const keyBuffer = (0, base64_js_1.decodeArrayBuffer)(keyData);
|
|
913
|
+
if (algorithmHint) {
|
|
914
|
+
algorithm = algorithmHint;
|
|
915
|
+
}
|
|
916
|
+
else {
|
|
917
|
+
// PKCS#8 PrivateKeyInfo embeds the same AlgorithmIdentifier OIDs as SPKI,
|
|
918
|
+
// so guessAlgorithmName / guessCurveName work on private key bytes too.
|
|
919
|
+
const hex = (0, hex_js_1.encodeArrayBuffer)(keyBuffer);
|
|
920
|
+
const algorithmName = (0, pemPublicToCrypto_js_1.guessAlgorithmName)(hex); // throws on unrecognised OID
|
|
921
|
+
if (algorithmName === 'ECDH' || algorithmName === 'ECDSA') {
|
|
922
|
+
const namedCurve = (0, pemPublicToCrypto_js_1.guessCurveName)(hex);
|
|
923
|
+
const curveMap = {
|
|
924
|
+
'P-256': 'ec:secp256r1',
|
|
925
|
+
'P-384': 'ec:secp384r1',
|
|
926
|
+
'P-521': 'ec:secp521r1',
|
|
927
|
+
};
|
|
928
|
+
const mapped = curveMap[namedCurve];
|
|
929
|
+
if (!mapped)
|
|
930
|
+
throw new errors_js_1.ConfigurationError(`Unsupported EC curve in private key: ${namedCurve}`);
|
|
931
|
+
algorithm = mapped;
|
|
932
|
+
}
|
|
933
|
+
else {
|
|
934
|
+
// RSA — determine key size by importing and reading modulus length from JWK
|
|
935
|
+
const tempKey = await crypto.subtle.importKey('pkcs8', keyBuffer, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, true, ['sign']);
|
|
936
|
+
const jwk = await crypto.subtle.exportKey('jwk', tempKey);
|
|
937
|
+
if (!jwk.n) {
|
|
938
|
+
throw new errors_js_1.ConfigurationError('Invalid RSA private key: missing modulus');
|
|
939
|
+
}
|
|
940
|
+
const modulusBits = base64urlByteLength(jwk.n) * 8;
|
|
941
|
+
if (modulusBits < declarations_js_1.MIN_ASYMMETRIC_KEY_SIZE_BITS) {
|
|
942
|
+
throw new errors_js_1.ConfigurationError(`RSA key size ${modulusBits} bits is below the minimum of ${declarations_js_1.MIN_ASYMMETRIC_KEY_SIZE_BITS} bits`);
|
|
943
|
+
}
|
|
944
|
+
algorithm = modulusBits <= 2048 ? 'rsa:2048' : 'rsa:4096';
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
// Determine Web Crypto algorithm and usages
|
|
948
|
+
let cryptoAlgorithm;
|
|
949
|
+
let keyUsages;
|
|
950
|
+
if (algorithm.startsWith('rsa:')) {
|
|
951
|
+
if (usage === 'encrypt') {
|
|
952
|
+
cryptoAlgorithm = rsaOaepSha1();
|
|
953
|
+
keyUsages = ['decrypt'];
|
|
954
|
+
}
|
|
955
|
+
else if (usage === 'sign') {
|
|
956
|
+
cryptoAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };
|
|
957
|
+
keyUsages = ['sign'];
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
throw new errors_js_1.ConfigurationError('RSA keys only support usage: encrypt or sign');
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
else if (algorithm.startsWith('ec:')) {
|
|
964
|
+
const curve = algorithm.split(':')[1];
|
|
965
|
+
const namedCurve = curve === 'secp256r1'
|
|
966
|
+
? 'P-256'
|
|
967
|
+
: curve === 'secp384r1'
|
|
968
|
+
? 'P-384'
|
|
969
|
+
: curve === 'secp521r1'
|
|
970
|
+
? 'P-521'
|
|
971
|
+
: (() => {
|
|
972
|
+
throw new errors_js_1.ConfigurationError(`Unsupported EC curve: ${curve}`);
|
|
973
|
+
})();
|
|
974
|
+
if (usage === 'derive') {
|
|
975
|
+
cryptoAlgorithm = { name: 'ECDH', namedCurve };
|
|
976
|
+
keyUsages = ['deriveBits'];
|
|
977
|
+
}
|
|
978
|
+
else if (usage === 'sign') {
|
|
979
|
+
cryptoAlgorithm = { name: 'ECDSA', namedCurve };
|
|
980
|
+
keyUsages = ['sign'];
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
throw new errors_js_1.ConfigurationError('EC keys only support usage: derive or sign');
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
else {
|
|
987
|
+
throw new errors_js_1.ConfigurationError(`Unsupported algorithm: ${algorithm}`);
|
|
988
|
+
}
|
|
989
|
+
// Import as CryptoKey
|
|
990
|
+
const cryptoKey = await crypto.subtle.importKey('pkcs8', keyBuffer, cryptoAlgorithm, extractable, keyUsages);
|
|
991
|
+
return wrapPrivateKey(cryptoKey, algorithm);
|
|
992
|
+
}
|
|
993
|
+
// ============================================================
|
|
994
|
+
// Key Export Functions (Opaque → PEM/JWK)
|
|
995
|
+
// ============================================================
|
|
996
|
+
/**
|
|
997
|
+
* Export an opaque public key to PEM format.
|
|
998
|
+
*/
|
|
999
|
+
async function exportPublicKeyPem(key) {
|
|
1000
|
+
const cryptoKey = unwrapKey(key);
|
|
1001
|
+
const keyBuffer = await crypto.subtle.exportKey('spki', cryptoKey);
|
|
1002
|
+
return (0, crypto_utils_js_1.formatAsPem)(keyBuffer, 'PUBLIC KEY');
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Export an opaque private key to PEM format.
|
|
1006
|
+
* ONLY USE FOR TESTING/DEVELOPMENT. Private keys should NOT be exportable in secure environments.
|
|
1007
|
+
*/
|
|
1008
|
+
async function exportPrivateKeyPem(key) {
|
|
1009
|
+
const cryptoKey = unwrapKey(key);
|
|
1010
|
+
const keyBuffer = await crypto.subtle.exportKey('pkcs8', cryptoKey);
|
|
1011
|
+
return (0, crypto_utils_js_1.formatAsPem)(keyBuffer, 'PRIVATE KEY');
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Export an opaque public key to JWK format.
|
|
1015
|
+
*/
|
|
1016
|
+
async function exportPublicKeyJwk(key) {
|
|
1017
|
+
const cryptoKey = unwrapKey(key);
|
|
1018
|
+
return await crypto.subtle.exportKey('jwk', cryptoKey);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Import raw key bytes as an opaque symmetric key.
|
|
1022
|
+
* Used for external keys (e.g., unwrapped from KAS).
|
|
1023
|
+
*/
|
|
1024
|
+
async function importSymmetricKey(keyBytes) {
|
|
1025
|
+
return wrapSymmetricKey(keyBytes);
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Split a symmetric key into N shares using XOR secret sharing.
|
|
1029
|
+
* Key bytes are extracted internally for splitting.
|
|
1030
|
+
* HSM implementations cannot extract bytes and should throw ConfigurationError.
|
|
1031
|
+
*/
|
|
1032
|
+
async function splitSymmetricKey(key, numShares) {
|
|
1033
|
+
const keyBytes = unwrapSymmetricKey(key);
|
|
1034
|
+
const splits = await (0, keysplit_js_1.keySplit)(keyBytes, numShares, exports.DefaultCryptoService);
|
|
1035
|
+
return splits.map(wrapSymmetricKey);
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Merge symmetric key shares back into the original key using XOR.
|
|
1039
|
+
* Key bytes are extracted internally for merging.
|
|
1040
|
+
*/
|
|
1041
|
+
async function mergeSymmetricKeys(shares) {
|
|
1042
|
+
const splitBytes = shares.map(unwrapSymmetricKey);
|
|
1043
|
+
const merged = (0, keysplit_js_1.keyMerge)(splitBytes);
|
|
1044
|
+
return wrapSymmetricKey(merged);
|
|
1045
|
+
}
|
|
299
1046
|
exports.DefaultCryptoService = {
|
|
300
1047
|
name: exports.name,
|
|
301
1048
|
method: exports.method,
|
|
302
|
-
cryptoToPemPair,
|
|
303
1049
|
decrypt,
|
|
304
1050
|
decryptWithPrivateKey,
|
|
1051
|
+
deriveKeyFromECDH,
|
|
1052
|
+
digest,
|
|
305
1053
|
encrypt,
|
|
306
1054
|
encryptWithPublicKey,
|
|
307
|
-
|
|
1055
|
+
exportPublicKeyJwk,
|
|
1056
|
+
exportPrivateKeyPem,
|
|
1057
|
+
exportPublicKeyPem,
|
|
1058
|
+
extractPublicKeyPem,
|
|
1059
|
+
generateECKeyPair,
|
|
308
1060
|
generateKey,
|
|
309
1061
|
generateKeyPair,
|
|
310
1062
|
generateSigningKeyPair,
|
|
311
|
-
|
|
1063
|
+
importPrivateKey,
|
|
1064
|
+
importPublicKey,
|
|
1065
|
+
importSymmetricKey,
|
|
1066
|
+
jwkToPublicKeyPem,
|
|
1067
|
+
mergeSymmetricKeys,
|
|
1068
|
+
parsePublicKeyPem,
|
|
312
1069
|
randomBytes,
|
|
313
|
-
|
|
1070
|
+
hmac,
|
|
1071
|
+
verifyHmac,
|
|
1072
|
+
sign,
|
|
1073
|
+
splitSymmetricKey,
|
|
1074
|
+
verify,
|
|
314
1075
|
};
|
|
315
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZGYzL3NyYy9jcnlwdG8vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7OztBQTRCSCxrQ0FjQztBQUVELHdDQWNDO0FBTUQsa0NBRUM7QUFPRCwwQ0FHQztBQU1ELHdEQVdDO0FBRUQsMENBZUM7QUFRRCxvREFtQkM7QUFLRCxvRUFFQztBQUVELGtDQUlDO0FBWUQsNENBS0M7QUFRRCxzREFxQkM7QUFVRCwwQkFRQztBQVNELDBCQU9DO0FBbUdELHdCQUlDO0FBUUQsb0JBZUM7QUFPRCx3QkFTQztBQWxYRCxrREFBaUQ7QUFDakQsNENBQXNDO0FBQ3RDLHVEQU0yQjtBQUMzQixzREFBMEU7QUFDMUUsdURBQXFFO0FBQ3JFLDBEQUErRTtBQUMvRSxnRUFBcUY7QUFHckYsNENBQTRDO0FBQzVDLE1BQU0sT0FBTyxHQUFlLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ3RDLFFBQUEsV0FBVyxHQUFHLE9BQU8sVUFBVSxFQUFFLE1BQU0sS0FBSyxXQUFXLENBQUM7QUFFeEQsUUFBQSxNQUFNLEdBQUcsNkNBQTZDLENBQUM7QUFDdkQsUUFBQSxJQUFJLEdBQUcsNEJBQTRCLENBQUM7QUFFakQ7OztHQUdHO0FBQ0gsU0FBZ0IsV0FBVyxDQUN6QixnQkFBd0IsOENBQTRCO0lBRXBELElBQUksQ0FBQyxhQUFhLElBQUksYUFBYSxHQUFHLDhDQUE0QixFQUFFLENBQUM7UUFDbkUsTUFBTSxJQUFJLDhCQUFrQixDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUNELE9BQU87UUFDTCxJQUFJLEVBQUUsVUFBVTtRQUNoQixJQUFJLEVBQUU7WUFDSixJQUFJLEVBQUUsT0FBTztTQUNkO1FBQ0QsYUFBYTtRQUNiLGNBQWMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFD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
|
|
1076
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZGYzL3NyYy9jcnlwdG8vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7OztBQThDSCxrQ0FjQztBQUVELHdDQWNDO0FBT0Qsa0NBR0M7QUEyRkQsMENBcUJDO0FBTUQsd0RBU0M7QUFTRCxvREFrQkM7QUFFRCxrQ0FJQztBQVlELDRDQUtDO0FBUUQsc0RBY0M7QUFVRCwwQkFRQztBQVNELDBCQU9DO0FBc0hELHdCQVNDO0FBNEtELG9CQWVDO0FBS0Qsd0JBZ0JDO0FBS0Qsd0JBU0M7QUFTRCxrREF3QkM7QUFxQkQsOENBNEJDO0FBcUNELDhDQW1EQztBQUtELG9CQWFDO0FBS0QsZ0NBY0M7QUEyQkQsOENBbURDO0FBS0QsOENBcUJDO0FBTUQsOENBb0NDO0FBU0QsMENBOERDO0FBS0QsNENBcUdDO0FBU0QsZ0RBSUM7QUFNRCxrREFJQztBQUtELGdEQUdDO0FBTUQsZ0RBRUM7QUFPRCw4Q0FPQztBQU1ELGdEQUlDO0FBM3VDRCxrREFBaUQ7QUFDakQsNENBQXNDO0FBQ3RDLHVEQWdCMkI7QUFDM0Isc0RBQTBFO0FBQzFFLHVEQUFxRTtBQUNyRSwwREFBK0U7QUFDL0UsZ0VBQXFGO0FBRXJGLCtCQUE4QztBQUM5QyxtRkFJa0Q7QUFDbEQsc0RBQTBEO0FBRTFELDRDQUE0QztBQUM1QyxNQUFNLGVBQWUsR0FBZSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUMzRCxNQUFNLG1CQUFtQixHQUFlLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzlDLFFBQUEsV0FBVyxHQUFHLE9BQU8sVUFBVSxFQUFFLE1BQU0sS0FBSyxXQUFXLENBQUM7QUFFeEQsUUFBQSxNQUFNLEdBQUcsNkNBQTZDLENBQUM7QUFDdkQsUUFBQSxJQUFJLEdBQUcsNEJBQTRCLENBQUM7QUFFakQ7OztHQUdHO0FBQ0gsU0FBZ0IsV0FBVyxDQUN6QixnQkFBd0IsOENBQTRCO0lBRXBELElBQUksQ0FBQyxhQUFhLElBQUksYUFBYSxHQUFHLDhDQUE0QixFQUFFLENBQUM7UUFDbkUsTUFBTSxJQUFJLDhCQUFrQixDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUNELE9BQU87UUFDTCxJQUFJLEVBQUUsVUFBVTtRQUNoQixJQUFJLEVBQUU7WUFDSixJQUFJLEVBQUUsT0FBTztTQUNkO1FBQ0QsYUFBYTtRQUNiLGNBQWMsRUFBRSxJQUFJLFVBQVUsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxpQ0FBaUM7S0FDdEYsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFnQixjQUFjLENBQzVCLGdCQUF3Qiw4Q0FBNEI7SUFFcEQsSUFBSSxDQUFDLGFBQWEsSUFBSSxhQUFhLEdBQUcsOENBQTRCLEVBQUUsQ0FBQztRQUNuRSxNQUFNLElBQUksOEJBQWtCLENBQUMsNEJBQTRCLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBQ0QsT0FBTztRQUNMLElBQUksRUFBRSxtQkFBbUI7UUFDekIsSUFBSSxFQUFFO1lBQ0osSUFBSSxFQUFFLFNBQVM7U0FDaEI7UUFDRCxhQUFhO1FBQ2IsY0FBYyxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLGlDQUFpQztLQUN0RixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsV0FBVyxDQUFDLE1BQWU7SUFDL0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxXQUFXLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELE9BQU8sZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDcEMsQ0FBQztBQUVELCtEQUErRDtBQUMvRCx5Q0FBeUM7QUFDekMsK0RBQStEO0FBRS9EOzs7R0FHRztBQUNILFNBQVMsYUFBYSxDQUFDLEdBQWMsRUFBRSxTQUF1QjtJQUM1RCxNQUFNLE1BQU0sR0FBUTtRQUNsQixNQUFNLEVBQUUsV0FBVztRQUNuQixTQUFTO1FBQ1QsU0FBUyxFQUFFLEdBQUc7S0FDZixDQUFDO0lBQ0YsSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDakMsTUFBTSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM3RCxDQUFDO1NBQU0sSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdkMsTUFBTSxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsS0FBSztZQUNWLFNBQVMsS0FBSyxXQUFXO2dCQUN2QixDQUFDLENBQUMsT0FBTztnQkFDVCxDQUFDLENBQUMsU0FBUyxLQUFLLFdBQVc7b0JBQ3pCLENBQUMsQ0FBQyxPQUFPO29CQUNULENBQUMsQ0FBQyxTQUFTLEtBQUssV0FBVzt3QkFDekIsQ0FBQyxDQUFDLE9BQU87d0JBQ1QsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUN0QixDQUFDO0lBQ0QsT0FBTyxNQUFtQixDQUFDO0FBQzdCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGNBQWMsQ0FBQyxHQUFjLEVBQUUsU0FBdUI7SUFDN0QsTUFBTSxNQUFNLEdBQVE7UUFDbEIsTUFBTSxFQUFFLFlBQVk7UUFDcEIsU0FBUztRQUNULFNBQVMsRUFBRSxHQUFHO0tBQ2YsQ0FBQztJQUNGLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztTQUFNLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLEtBQUs7WUFDVixTQUFTLEtBQUssV0FBVztnQkFDdkIsQ0FBQyxDQUFDLE9BQU87Z0JBQ1QsQ0FBQyxDQUFDLFNBQVMsS0FBSyxXQUFXO29CQUN6QixDQUFDLENBQUMsT0FBTztvQkFDVCxDQUFDLENBQUMsU0FBUyxLQUFLLFdBQVc7d0JBQ3pCLENBQUMsQ0FBQyxPQUFPO3dCQUNULENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDdEIsQ0FBQztJQUNELE9BQU8sTUFBb0IsQ0FBQztBQUM5QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxTQUFTLENBQUMsR0FBMkI7SUFDNUMsT0FBUSxHQUFXLENBQUMsU0FBUyxDQUFDO0FBQ2hDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGdCQUFnQixDQUFDLFFBQW9CO0lBQzVDLE9BQU87UUFDTCxNQUFNLEVBQUUsY0FBYztRQUN0QixNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsT0FBTztRQUNwQyxTQUFTLEVBQUUsUUFBUTtLQUNKLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsa0JBQWtCLENBQUMsR0FBaUI7SUFDM0MsT0FBUSxHQUFXLENBQUMsU0FBUyxDQUFDO0FBQ2hDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0ksS0FBSyxVQUFVLGVBQWUsQ0FBQyxJQUFhO0lBQ2pELE1BQU0sT0FBTyxHQUFHLElBQUksSUFBSSw4Q0FBNEIsQ0FBQztJQUNyRCxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO0lBRXRGLG1DQUFtQztJQUNuQyxJQUFJLFNBQXVCLENBQUM7SUFDNUIsSUFBSSxPQUFPLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDckIsU0FBUyxHQUFHLFVBQVUsQ0FBQztJQUN6QixDQUFDO1NBQU0sSUFBSSxPQUFPLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDNUIsU0FBUyxHQUFHLFVBQVUsQ0FBQztJQUN6QixDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sSUFBSSw4QkFBa0IsQ0FDMUIsNkJBQTZCLE9BQU8scUNBQXFDLENBQzFFLENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTztRQUNMLFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUM7UUFDdEQsVUFBVSxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQztLQUMxRCxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7R0FHRztBQUNJLEtBQUssVUFBVSxzQkFBc0I7SUFDMUMsTUFBTSxTQUFTLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0lBRXRGLE1BQU0sU0FBUyxHQUFpQixVQUFVLENBQUM7SUFDM0MsT0FBTztRQUNMLFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUM7UUFDdEQsVUFBVSxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQztLQUMxRCxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSxvQkFBb0IsQ0FDeEMsT0FBOEIsRUFDOUIsU0FBb0I7SUFFcEIsSUFBSSxhQUEyQixDQUFDO0lBRWhDLGlDQUFpQztJQUNqQyxJQUFJLFFBQVEsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxjQUFjLEVBQUUsQ0FBQztRQUM3RCw2RkFBNkY7UUFDN0YsYUFBYSxHQUFHLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlDLENBQUM7U0FBTSxDQUFDO1FBQ04saUJBQWlCO1FBQ2pCLGFBQWEsR0FBSSxPQUFrQixDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkMsTUFBTSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFBRSxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDM0YsT0FBTyxrQkFBTSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN4QyxDQUFDO0FBRU0sS0FBSyxVQUFVLFdBQVcsQ0FBQyxVQUFrQjtJQUNsRCxNQUFNLENBQUMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNyQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFCLE9BQU8sQ0FBQyxDQUFDO0FBQ1gsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNJLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxNQUFjO0lBQ25ELHFEQUFxRDtJQUNyRCxNQUFNLENBQUMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNqQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFCLE9BQU8sSUFBQSwwQkFBUyxFQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM3QixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSSxLQUFLLFVBQVUscUJBQXFCLENBQ3pDLGdCQUF3QixFQUN4QixVQUFzQjtJQUV0QixPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sZ0JBQWdCLEtBQUssUUFBUSxFQUFFLGlDQUFpQyxDQUFDLENBQUM7SUFFeEYsTUFBTSxTQUFTLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQ3pDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxFQUNwQixTQUFTLEVBQ1QsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLENBQ2pDLENBQUM7SUFDRixNQUFNLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMzQyxPQUFPLGtCQUFNLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQWdCLE9BQU8sQ0FDckIsT0FBZSxFQUNmLEdBQWlCLEVBQ2pCLEVBQVUsRUFDVixTQUF3QixFQUN4QixPQUFnQjtJQUVoQixPQUFPLFVBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLE9BQU8sQ0FDckIsT0FBOEIsRUFDOUIsR0FBaUIsRUFDakIsRUFBVSxFQUNWLFNBQXdCO0lBRXhCLE9BQU8sVUFBVSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2pELENBQUM7QUFFRCxLQUFLLFVBQVUsVUFBVSxDQUN2QixPQUE4QixFQUM5QixHQUFpQixFQUNqQixFQUFVLEVBQ1YsU0FBd0I7SUFFeEIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLENBQUM7SUFDaEMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLENBQUM7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLENBQUM7SUFFM0IsK0NBQStDO0lBQy9DLElBQUksYUFBMkIsQ0FBQztJQUNoQyxJQUFJLFFBQVEsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxjQUFjLEVBQUUsQ0FBQztRQUM3RCw2RkFBNkY7UUFDN0YsYUFBYSxHQUFHLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlDLENBQUM7U0FBTSxDQUFDO1FBQ04saUJBQWlCO1FBQ2pCLGFBQWEsR0FBSSxPQUFrQixDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyx5QkFBeUIsQ0FBQyxFQUFFLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFFL0Qsd0NBQXdDO0lBQ3hDLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sV0FBVyxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztJQUM5RCxNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDekYsSUFBSSxhQUFhLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3JDLE9BQU87WUFDTCxPQUFPLEVBQUUsa0JBQU0sQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN4RCxPQUFPLEVBQUUsa0JBQU0sQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ3RELENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTztRQUNMLE9BQU8sRUFBRSxrQkFBTSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUM7S0FDM0MsQ0FBQztBQUNKLENBQUM7QUFFRCxLQUFLLFVBQVUsVUFBVSxDQUN2QixPQUFlLEVBQ2YsR0FBaUIsRUFDakIsRUFBVSxFQUNWLFNBQXdCLEVBQ3hCLE9BQWdCO0lBRWhCLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQ2hDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQzVCLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDO0lBRTNCLElBQUksYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUU1Qyx3REFBd0Q7SUFDeEQsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNaLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM5QyxNQUFNLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxhQUFhLENBQUMsVUFBVSxHQUFHLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN2RixVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksVUFBVSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2pELFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUUsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3hFLGFBQWEsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyx5QkFBeUIsQ0FBQyxFQUFFLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFFL0Qsd0NBQXdDO0lBQ3hDLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sV0FBVyxHQUFHLE1BQU0sVUFBVSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztJQUM5RCxhQUFhLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUV0QyxNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNO1NBQ2xDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsV0FBVyxFQUFFLGFBQWEsQ0FBQztRQUNuRCxzRUFBc0U7U0FDckUsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDYixJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksd0JBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QixDQUFDO1FBRUQsTUFBTSxHQUFHLENBQUM7SUFDWixDQUFDLENBQUMsQ0FBQztJQUNMLE9BQU8sRUFBRSxPQUFPLEVBQUUsa0JBQU0sQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztBQUN4RCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsUUFBb0IsRUFBRSxTQUFzQztJQUM5RSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxlQUFlLENBQUMsQ0FBQztBQUNwRixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLHlCQUF5QixDQUNoQyxFQUFVLEVBQ1YsU0FBd0I7SUFFeEIsSUFBSSxlQUFlLEdBQUcsU0FBUyxDQUFDO0lBQ2hDLElBQUksU0FBUyxLQUFLLHFCQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDekMsZUFBZSxHQUFHLFNBQVMsQ0FBQztJQUM5QixDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksRUFBRSxlQUFlO1FBQ3JCLEVBQUUsRUFBRSxFQUFFLENBQUMsYUFBYSxFQUFFO0tBQ3ZCLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFFSDs7OztHQUlHO0FBQ0gsU0FBZ0IsTUFBTSxDQUFDLEdBQVc7SUFDaEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUUxQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDdkMsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMseUJBQXlCLENBQUMsU0FBcUM7SUFJdEUsUUFBUSxTQUFTLEVBQUUsQ0FBQztRQUNsQixLQUFLLE9BQU87WUFDVixPQUFPO2dCQUNMLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO2dCQUM1RCxVQUFVLEVBQUUsbUJBQW1CO2FBQ2hDLENBQUM7UUFDSixLQUFLLE9BQU87WUFDVixPQUFPO2dCQUNMLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRTtnQkFDcEQsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFpQjthQUM5RCxDQUFDO1FBQ0osS0FBSyxPQUFPO1lBQ1YsT0FBTztnQkFDTCxZQUFZLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUU7Z0JBQ3BELFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBaUI7YUFDOUQsQ0FBQztRQUNKLEtBQUssT0FBTztZQUNWLE9BQU87Z0JBQ0wsWUFBWSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFO2dCQUNwRCxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQWlCO2FBQzlELENBQUM7UUFDSjtZQUNFLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyxrQ0FBa0MsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUNoRixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsY0FBYyxDQUFDLFNBQXFCLEVBQUUsU0FBcUM7SUFDbEYsSUFBSSxTQUFTLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDMUIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNyQyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN0QyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRW5DLDJEQUEyRDtJQUMzRCxNQUFNLGdCQUFnQixHQUFHLENBQUMsR0FBZSxFQUFjLEVBQUU7UUFDdkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7WUFBRSxDQUFDLEVBQUUsQ0FBQztRQUMvQyxPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEIsQ0FBQyxDQUFDO0lBRUYsSUFBSSxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkMsSUFBSSxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFbkMsZ0VBQWdFO0lBQ2hFLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDeEIsUUFBUSxHQUFHLE1BQU0sQ0FBQztJQUNwQixDQUFDO0lBQ0QsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUM7UUFDdkIsTUFBTSxNQUFNLEdBQUcsSUFBSSxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNuRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN4QixRQUFRLEdBQUcsTUFBTSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxzREFBc0Q7SUFDdEQsaUNBQWlDO0lBQ2pDLE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRWxFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN6QyxxRUFBcUU7SUFDckUsa0VBQWtFO0lBQ2xFLE1BQU0sUUFBUSxHQUFHLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksVUFBVSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMxRixNQUFNLE1BQU0sR0FBRyxJQUFJLFVBQVUsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQztJQUM1RCxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQ2pCLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXBELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGNBQWMsQ0FBQyxTQUFxQixFQUFFLFNBQXFDO0lBQ2xGLElBQUksU0FBUyxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQzFCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCw2REFBNkQ7SUFDN0QsSUFBSSxZQUFvQixDQUFDO0lBQ3pCLFFBQVEsU0FBUyxFQUFFLENBQUM7UUFDbEIsS0FBSyxPQUFPO1lBQ1YsWUFBWSxHQUFHLEVBQUUsQ0FBQztZQUNsQixNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsWUFBWSxHQUFHLEVBQUUsQ0FBQztZQUNsQixNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsWUFBWSxHQUFHLEVBQUUsQ0FBQztZQUNsQixNQUFNO1FBQ1I7WUFDRSxNQUFNLElBQUksOEJBQWtCLENBQUMsNkNBQTZDLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVELCtDQUErQztJQUMvQyxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUMxQixNQUFNLElBQUksOEJBQWtCLENBQUMsMENBQTBDLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQsa0VBQWtFO0lBQ2xFLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNmLElBQUksU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDO1FBQzdCLDZEQUE2RDtRQUM3RCxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQy9DLElBQUksYUFBYSxLQUFLLENBQUMsSUFBSSxhQUFhLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0MsTUFBTSxJQUFJLDhCQUFrQixDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDbEYsQ0FBQztRQUNELE1BQU0sSUFBSSxDQUFDLEdBQUcsYUFBYSxDQUFDO1FBQzVCLElBQUksTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUM5QixNQUFNLElBQUksOEJBQWtCLENBQUMsNkRBQTZELENBQUMsQ0FBQztRQUM5RixDQUFDO0lBQ0gsQ0FBQztTQUFNLENBQUM7UUFDTixrQ0FBa0M7UUFDbEMsTUFBTSxJQUFJLENBQUMsQ0FBQztJQUNkLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsSUFBSSxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDL0IsTUFBTSxJQUFJLDhCQUFrQixDQUFDLCtDQUErQyxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUNELE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbkMsTUFBTSxJQUFJLENBQUMsQ0FBQztJQUNaLElBQUksQ0FBQyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBQUMsQ0FBQztJQUMvQyxNQUFNLElBQUksSUFBSSxDQUFDO0lBRWYsa0JBQWtCO0lBQ2xCLElBQUksU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQy9CLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO0lBQ2hGLENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ25DLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDWixJQUFJLENBQUMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFFL0MseUNBQXlDO0lBQ3pDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLFlBQVksRUFBRSxDQUFDO1FBQzFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pCLENBQUM7SUFDRCxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sR0FBRyxZQUFZLEVBQUUsQ0FBQztRQUMxQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqQixDQUFDO0lBRUQsMEJBQTBCO0lBQzFCLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNoRCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxZQUFZLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFlBQVksR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTNDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxJQUFJLENBQ3hCLElBQWdCLEVBQ2hCLFVBQXNCLEVBQ3RCLFNBQXFDO0lBRXJDLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyx5QkFBeUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUU1RCxnQ0FBZ0M7SUFDaEMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRWxDLGdCQUFnQjtJQUNoQixNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFbEUsbURBQW1EO0lBQ25ELE9BQU8sY0FBYyxDQUFDLElBQUksVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQzlELENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxNQUFNLENBQzFCLElBQWdCLEVBQ2hCLFNBQXFCLEVBQ3JCLFNBQW9CLEVBQ3BCLFNBQXFDO0lBRXJDLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyx5QkFBeUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUU1RCxnQ0FBZ0M7SUFDaEMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRWpDLG1EQUFtRDtJQUNuRCxNQUFNLGFBQWEsR0FBRyxjQUFjLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBRTNELHVCQUF1QjtJQUN2QixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ3BFLENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxNQUFNLENBQUMsU0FBd0IsRUFBRSxJQUFnQjtJQUNyRSxnREFBZ0Q7SUFDaEQsTUFBTSxlQUFlLEdBQW9CLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUMzRSxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQywrQkFBK0IsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDL0QsT0FBTyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxTQUFpQixFQUNqQixZQUFxQjtJQUVyQixnREFBZ0Q7SUFDaEQsSUFBSSxTQUFTLENBQUMsUUFBUSxDQUFDLDZCQUE2QixDQUFDLEVBQUUsQ0FBQztRQUN0RCxJQUFJLEdBQUcsR0FBRyxZQUFZLENBQUM7UUFDdkIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ1QsOENBQThDO1lBQzlDLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsdUNBQXVDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDaEYsTUFBTSxTQUFTLEdBQUcsSUFBQSw2QkFBWSxFQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sR0FBRyxHQUFHLElBQUEsMEJBQVMsRUFBQyxTQUFTLENBQUMsQ0FBQztZQUNqQyxHQUFHLEdBQUcsSUFBQSwrQkFBUSxFQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3RCLENBQUM7UUFDRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUEsaUJBQVUsRUFBQyxTQUFTLEVBQUUsR0FBRyxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDckUsT0FBTyxJQUFBLGlCQUFVLEVBQUMsSUFBSSxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVELGlEQUFpRDtJQUNqRCxJQUFJLFNBQVMsQ0FBQyxRQUFRLENBQUMsNEJBQTRCLENBQUMsRUFBRSxDQUFDO1FBQ3JELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLElBQUksOEJBQWtCLENBQUMsdURBQXVELENBQUMsQ0FBQztBQUN4RixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLEtBQWM7SUFDdkMsUUFBUSxLQUFLLEVBQUUsQ0FBQztRQUNkLEtBQUssT0FBTztZQUNWLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLEtBQUssT0FBTztZQUNWLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLEtBQUssT0FBTztZQUNWLE9BQU8sT0FBTyxDQUFDO1FBQ2pCO1lBQ0UsTUFBTSxJQUFJLDhCQUFrQixDQUFDLHNCQUFzQixLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSSxLQUFLLFVBQVUsaUJBQWlCLENBQUMsUUFBaUIsT0FBTztJQUM5RCxNQUFNLFVBQVUsR0FBRyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUU1QywyQ0FBMkM7SUFDM0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFO1FBQ2xGLFlBQVk7S0FDYixDQUFDLENBQUM7SUFFSCxtQ0FBbUM7SUFDbkMsSUFBSSxTQUF1QixDQUFDO0lBQzVCLFFBQVEsVUFBVSxFQUFFLENBQUM7UUFDbkIsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGNBQWMsQ0FBQztZQUMzQixNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGNBQWMsQ0FBQztZQUMzQixNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGNBQWMsQ0FBQztZQUMzQixNQUFNO1FBQ1I7WUFDRSxNQUFNLElBQUksOEJBQWtCLENBQUMsc0JBQXNCLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDckUsQ0FBQztJQUVELE9BQU87UUFDTCxTQUFTLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDO1FBQ3RELFVBQVUsRUFBRSxjQUFjLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUM7S0FDMUQsQ0FBQztBQUNKLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBVSxDQUFDO0FBR2pFOzs7R0FHRztBQUNILFNBQVMsbUJBQW1CLENBQUMsU0FBaUI7SUFDNUMsa0RBQWtEO0lBQ2xELE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxNQUFNLE1BQU0sR0FBRyxTQUFTLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMvQyxPQUFPLElBQUEsNkJBQVksRUFBQyxNQUFNLENBQUMsQ0FBQyxVQUFVLENBQUM7QUFDekMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsMkJBQTJCLENBQUMsT0FBb0I7SUFDdkQsaUNBQWlDO0lBQ2pDLE1BQU0sTUFBTSxHQUFHLElBQUEsMEJBQVMsRUFBQyxPQUFPLENBQUMsQ0FBQztJQUVsQyxpRUFBaUU7SUFDakUsTUFBTSxTQUFTLEdBQUcsSUFBQSxxQ0FBYyxFQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXpDLE9BQU8sU0FBNkIsQ0FBQztBQUN2QyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0ksS0FBSyxVQUFVLGlCQUFpQixDQUNyQyxVQUFzQixFQUN0QixTQUFvQixFQUNwQixVQUFzQjtJQUV0QixpQ0FBaUM7SUFDakMsTUFBTSxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDL0MsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTdDLDhCQUE4QjtJQUM5QixNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO0lBQzlCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRCxnQ0FBZ0M7SUFDaEMsTUFBTSxTQUFTLEdBQTRCO1FBQ3pDLE9BQU8sRUFBRSxHQUFHO1FBQ1osT0FBTyxFQUFFLEdBQUc7UUFDWixPQUFPLEVBQUUsR0FBRyxFQUFFLG9DQUFvQztLQUNuRCxDQUFDO0lBQ0YsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTlCLG9DQUFvQztJQUNwQyxNQUFNLFlBQVksR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUNqRCxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxFQUN6QyxnQkFBZ0IsRUFDaEIsSUFBSSxDQUNMLENBQUM7SUFFRiw0Q0FBNEM7SUFDNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBRWpHLGtDQUFrQztJQUNsQyxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsU0FBUyxJQUFJLEdBQUcsQ0FBQztJQUM5QyxNQUFNLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUM5QztRQUNFLElBQUksRUFBRSxNQUFNO1FBQ1osSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO1FBQ3JCLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtRQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUksSUFBSSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7S0FDM0MsRUFDRCxPQUFPLEVBQ1AsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsRUFDdEMsSUFBSSxFQUNKLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUN2QixDQUFDO0lBRUYsK0RBQStEO0lBQy9ELE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2xFLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBRUQ7O0dBRUc7QUFDSSxLQUFLLFVBQVUsSUFBSSxDQUFDLElBQWdCLEVBQUUsR0FBaUI7SUFDNUQsd0NBQXdDO0lBQ3hDLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sU0FBUyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQzdDLEtBQUssRUFDTCxRQUFRLEVBQ1IsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDakMsS0FBSyxFQUNMLENBQUMsTUFBTSxDQUFDLENBQ1QsQ0FBQztJQUVGLE1BQU0sU0FBUyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwRSxPQUFPLElBQUksVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ25DLENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxVQUFVLENBQzlCLElBQWdCLEVBQ2hCLFNBQXFCLEVBQ3JCLEdBQWlCO0lBRWpCLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sU0FBUyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQzdDLEtBQUssRUFDTCxRQUFRLEVBQ1IsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFDakMsS0FBSyxFQUNMLENBQUMsUUFBUSxDQUFDLENBQ1gsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSwwQkFBMEIsQ0FBQyxPQUFvQjtJQUM1RCxNQUFNLEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUN2QyxNQUFNLEVBQ04sT0FBTyxFQUNQLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQ3JDLElBQUksRUFBRSxjQUFjO0lBQ3BCLENBQUMsU0FBUyxDQUFDLENBQ1osQ0FBQztJQUNGLE1BQU0sR0FBRyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3RELElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDWCxNQUFNLElBQUksOEJBQWtCLENBQUMsa0NBQWtDLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBQ0QsdUNBQXVDO0lBQ3ZDLGlEQUFpRDtJQUNqRCxPQUFPLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUVEOzs7R0FHRztBQUNJLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxHQUFXO0lBQ2pELGlEQUFpRDtJQUNqRCxJQUFJLFlBQVksR0FBRyxHQUFHLENBQUM7SUFDdkIsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLDZCQUE2QixDQUFDLEVBQUUsQ0FBQztRQUNoRCxZQUFZLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsNEJBQTRCLENBQUMsRUFBRSxDQUFDO1FBQ3pELE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyx1REFBdUQsQ0FBQyxDQUFDO0lBQ3hGLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFBLDZCQUFZLEVBQUMsSUFBQSxxQ0FBbUIsRUFBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO0lBRWhFLHFEQUFxRDtJQUNyRCxJQUFJLENBQUM7UUFDSCxNQUFNLFdBQVcsR0FBRyxNQUFNLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlELElBQUksU0FBcUMsQ0FBQztRQUMxQyxJQUFJLFdBQVcsR0FBRyw4Q0FBNEIsRUFBRSxDQUFDO1lBQy9DLE1BQU0sSUFBSSw4QkFBa0IsQ0FDMUIsZ0JBQWdCLFdBQVcsaUNBQWlDLDhDQUE0QixPQUFPLENBQ2hHLENBQUM7UUFDSixDQUFDO2FBQU0sSUFBSSxXQUFXLElBQUksSUFBSSxFQUFFLENBQUM7WUFDL0IsU0FBUyxHQUFHLFVBQVUsQ0FBQztRQUN6QixDQUFDO2FBQU0sSUFBSSxXQUFXLElBQUksSUFBSSxFQUFFLENBQUM7WUFDL0IsU0FBUyxHQUFHLFVBQVUsQ0FBQztRQUN6QixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyw2QkFBNkIsV0FBVyxPQUFPLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBQ0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCw4Q0FBOEM7UUFDOUMsSUFBSSxDQUFDLFlBQVksOEJBQWtCLEVBQUUsQ0FBQztZQUNwQyxNQUFNLENBQUMsQ0FBQztRQUNWLENBQUM7UUFDRCw4QkFBOEI7SUFDaEMsQ0FBQztJQUVELGdDQUFnQztJQUNoQyxJQUFJLENBQUM7UUFDSCxNQUFNLGFBQWEsR0FBRywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzRCxNQUFNLFFBQVEsR0FBRztZQUNmLE9BQU8sRUFBRSxjQUFjO1lBQ3ZCLE9BQU8sRUFBRSxjQUFjO1lBQ3ZCLE9BQU8sRUFBRSxjQUFjO1NBQ2YsQ0FBQztRQUNYLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUNuRSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AscUJBQXFCO0lBQ3ZCLENBQUM7SUFFRCxNQUFNLElBQUksOEJBQWtCLENBQUMsaUVBQWlFLENBQUMsQ0FBQztBQUNsRyxDQUFDO0FBRUQ7O0dBRUc7QUFDSSxLQUFLLFVBQVUsaUJBQWlCLENBQUMsR0FBZTtJQUNyRCxJQUFJLEdBQWMsQ0FBQztJQUVuQixJQUFJLEdBQUcsQ0FBQyxHQUFHLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDdEIsVUFBVTtRQUNWLEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUU7WUFDM0YsU0FBUztTQUNWLENBQUMsQ0FBQztJQUNMLENBQUM7U0FBTSxJQUFJLEdBQUcsQ0FBQyxHQUFHLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDNUIsU0FBUztRQUNULE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFDcEIsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2RCxNQUFNLElBQUksOEJBQWtCLENBQUMseUJBQXlCLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDL0QsQ0FBQztRQUNELEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDL0YsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLElBQUksOEJBQWtCLENBQUMsNkJBQTZCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5RCxPQUFPLElBQUEsNkJBQVcsRUFBQyxVQUFVLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVEOzs7R0FHRztBQUNJLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxZQUFvQjtJQUMxRCxNQUFNLGFBQWEsR0FBRyxJQUFBLHFDQUFtQixFQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3hELE1BQU0sU0FBUyxHQUFHLElBQUEsNkJBQVksRUFBQyxhQUFhLENBQUMsQ0FBQztJQUM5QyxNQUFNLEdBQUcsR0FBRyxJQUFBLDBCQUFTLEVBQUMsU0FBUyxDQUFDLENBQUM7SUFFakMsNEJBQTRCO0lBQzVCLE1BQU0sYUFBYSxHQUFHLElBQUEseUNBQWtCLEVBQUMsR0FBRyxDQUFDLENBQUM7SUFFOUMsSUFBSSxhQUFhLEtBQUssTUFBTSxJQUFJLGFBQWEsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUMxRCxpQ0FBaUM7UUFDakMsTUFBTSxVQUFVLEdBQUcsSUFBQSxxQ0FBYyxFQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sR0FBRyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQ3ZDLE1BQU0sRUFDTixTQUFTLEVBQ1QsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxFQUM3QixJQUFJLEVBQ0osQ0FBQyxRQUFRLENBQUMsQ0FDWCxDQUFDO1FBQ0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdEQsb0NBQW9DO1FBQ3BDLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUM7UUFDL0IsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzVCLENBQUM7U0FBTSxDQUFDO1FBQ04sVUFBVTtRQUNWLE1BQU0sR0FBRyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQ3ZDLE1BQU0sRUFDTixTQUFTLEVBQ1QsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUM5QyxJQUFJLEVBQ0osQ0FBQyxRQUFRLENBQUMsQ0FDWCxDQUFDO1FBQ0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdEQsb0NBQW9DO1FBQ3BDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQztRQUMxQixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUN2QixDQUFDO0FBQ0gsQ0FBQztBQUVELCtEQUErRDtBQUMvRCxzQ0FBc0M7QUFDdEMsK0RBQStEO0FBRS9EOztHQUVHO0FBQ0ksS0FBSyxVQUFVLGVBQWUsQ0FBQyxHQUFXLEVBQUUsT0FBbUI7SUFDcEUsTUFBTSxFQUFFLEtBQUssR0FBRyxTQUFTLEVBQUUsV0FBVyxHQUFHLElBQUksRUFBRSxhQUFhLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFFekUsNEVBQTRFO0lBQzVFLE1BQU0sT0FBTyxHQUFHLE1BQU0saUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDN0MsTUFBTSxTQUFTLEdBQUcsYUFBYSxJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUM7SUFFckQsc0ZBQXNGO0lBQ3RGLHdGQUF3RjtJQUN4RixNQUFNLE9BQU8sR0FBRyxJQUFBLHFDQUFtQixFQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxNQUFNLFNBQVMsR0FBRyxJQUFBLDZCQUFZLEVBQUMsT0FBTyxDQUFDLENBQUM7SUFFeEMsd0VBQXdFO0lBQ3hFLElBQUksZUFBMEQsQ0FBQztJQUMvRCxJQUFJLFNBQXFCLENBQUM7SUFFMUIsSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDakMsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDeEIsZUFBZSxHQUFHLFdBQVcsRUFBRSxDQUFDO1lBQ2hDLFNBQVMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFCLENBQUM7YUFBTSxJQUFJLEtBQUssS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUM1QixlQUFlLEdBQUcsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO1lBQ2pFLFNBQVMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLDhCQUFrQixDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDL0UsQ0FBQztJQUNILENBQUM7U0FBTSxJQUFJLFNBQVMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN2QyxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sVUFBVSxHQUNkLEtBQUssS0FBSyxXQUFXO1lBQ25CLENBQUMsQ0FBQyxPQUFPO1lBQ1QsQ0FBQyxDQUFDLEtBQUssS0FBSyxXQUFXO2dCQUNyQixDQUFDLENBQUMsT0FBTztnQkFDVCxDQUFDLENBQUMsS0FBSyxLQUFLLFdBQVc7b0JBQ3JCLENBQUMsQ0FBQyxPQUFPO29CQUNULENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRTt3QkFDSixNQUFNLElBQUksOEJBQWtCLENBQUMseUJBQXlCLEtBQUssRUFBRSxDQUFDLENBQUM7b0JBQ2pFLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFFZixJQUFJLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN2QixlQUFlLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDO1lBQy9DLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFDakIsQ0FBQzthQUFNLElBQUksS0FBSyxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQzVCLGVBQWUsR0FBRyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDaEQsU0FBUyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekIsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLElBQUksOEJBQWtCLENBQUMsNENBQTRDLENBQUMsQ0FBQztRQUM3RSxDQUFDO0lBQ0gsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLElBQUksOEJBQWtCLENBQUMsMEJBQTBCLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVELHNCQUFzQjtJQUN0QixNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUM3QyxNQUFNLEVBQ04sU0FBUyxFQUNULGVBQWUsRUFDZixXQUFXLEVBQ1gsU0FBUyxDQUNWLENBQUM7SUFFRixPQUFPLGFBQWEsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVEOztHQUVHO0FBQ0ksS0FBSyxVQUFVLGdCQUFnQixDQUFDLEdBQVcsRUFBRSxPQUFtQjtJQUNyRSxNQUFNLEVBQUUsS0FBSyxHQUFHLFNBQVMsRUFBRSxXQUFXLEdBQUcsSUFBSSxFQUFFLGFBQWEsRUFBRSxHQUFHLE9BQU8sQ0FBQztJQUV6RSx3RUFBd0U7SUFDeEUsOEVBQThFO0lBQzlFLElBQUksU0FBdUIsQ0FBQztJQUU1QixNQUFNLE9BQU8sR0FBRyxJQUFBLHFDQUFtQixFQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sU0FBUyxHQUFHLElBQUEsNkJBQVksRUFBQyxPQUFPLENBQUMsQ0FBQztJQUV4QyxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQ2xCLFNBQVMsR0FBRyxhQUFhLENBQUM7SUFDNUIsQ0FBQztTQUFNLENBQUM7UUFDTiwwRUFBMEU7UUFDMUUsd0VBQXdFO1FBQ3hFLE1BQU0sR0FBRyxHQUFHLElBQUEsMEJBQVMsRUFBQyxTQUFTLENBQUMsQ0FBQztRQUNqQyxNQUFNLGFBQWEsR0FBRyxJQUFBLHlDQUFrQixFQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsNkJBQTZCO1FBQzVFLElBQUksYUFBYSxLQUFLLE1BQU0sSUFBSSxhQUFhLEtBQUssT0FBTyxFQUFFLENBQUM7WUFDMUQsTUFBTSxVQUFVLEdBQUcsSUFBQSxxQ0FBYyxFQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sUUFBUSxHQUFpQztnQkFDN0MsT0FBTyxFQUFFLGNBQWM7Z0JBQ3ZCLE9BQU8sRUFBRSxjQUFjO2dCQUN2QixPQUFPLEVBQUUsY0FBYzthQUN4QixDQUFDO1lBQ0YsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3BDLElBQUksQ0FBQyxNQUFNO2dCQUNULE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyx3Q0FBd0MsVUFBVSxFQUFFLENBQUMsQ0FBQztZQUNyRixTQUFTLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLENBQUM7YUFBTSxDQUFDO1lBQ04sNEVBQTRFO1lBQzVFLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQzNDLE9BQU8sRUFDUCxTQUFTLEVBQ1QsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUM5QyxJQUFJLEVBQ0osQ0FBQyxNQUFNLENBQUMsQ0FDVCxDQUFDO1lBQ0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDMUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxNQUFNLElBQUksOEJBQWtCLENBQUMsMENBQTBDLENBQUMsQ0FBQztZQUMzRSxDQUFDO1lBQ0QsTUFBTSxXQUFXLEdBQUcsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNuRCxJQUFJLFdBQVcsR0FBRyw4Q0FBNEIsRUFBRSxDQUFDO2dCQUMvQyxNQUFNLElBQUksOEJBQWtCLENBQzFCLGdCQUFnQixXQUFXLGlDQUFpQyw4Q0FBNEIsT0FBTyxDQUNoRyxDQUFDO1lBQ0osQ0FBQztZQUNELFNBQVMsR0FBRyxXQUFXLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztRQUM1RCxDQUFDO0lBQ0gsQ0FBQztJQUVELDRDQUE0QztJQUM1QyxJQUFJLGVBQTBELENBQUM7SUFDL0QsSUFBSSxTQUFxQixDQUFDO0lBRTFCLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pDLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3hCLGVBQWUsR0FBRyxXQUFXLEVBQUUsQ0FBQztZQUNoQyxTQUFTLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQixDQUFDO2FBQU0sSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDNUIsZUFBZSxHQUFHLEVBQUUsSUFBSSxFQUFFLG1CQUFtQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQztZQUNqRSxTQUFTLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQy9FLENBQUM7SUFDSCxDQUFDO1NBQU0sSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdkMsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0QyxNQUFNLFVBQVUsR0FDZCxLQUFLLEtBQUssV0FBVztZQUNuQixDQUFDLENBQUMsT0FBTztZQUNULENBQUMsQ0FBQyxLQUFLLEtBQUssV0FBVztnQkFDckIsQ0FBQyxDQUFDLE9BQU87Z0JBQ1QsQ0FBQyxDQUFDLEtBQUssS0FBSyxXQUFXO29CQUNyQixDQUFDLENBQUMsT0FBTztvQkFDVCxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUU7d0JBQ0osTUFBTSxJQUFJLDhCQUFrQixDQUFDLHlCQUF5QixLQUFLLEVBQUUsQ0FBQyxDQUFDO29CQUNqRSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBRWYsSUFBSSxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdkIsZUFBZSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsQ0FBQztZQUMvQyxTQUFTLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3QixDQUFDO2FBQU0sSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDNUIsZUFBZSxHQUFHLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQztZQUNoRCxTQUFTLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1FBQzdFLENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sSUFBSSw4QkFBa0IsQ0FBQywwQkFBMEIsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBRUQsc0JBQXNCO0lBQ3RCLE1BQU0sU0FBUyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQzdDLE9BQU8sRUFDUCxTQUFTLEVBQ1QsZUFBZSxFQUNmLFdBQVcsRUFDWCxTQUFTLENBQ1YsQ0FBQztJQUVGLE9BQU8sY0FBYyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQsK0RBQStEO0FBQy9ELDBDQUEwQztBQUMxQywrREFBK0Q7QUFFL0Q7O0dBRUc7QUFDSSxLQUFLLFVBQVUsa0JBQWtCLENBQUMsR0FBYztJQUNyRCxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsTUFBTSxTQUFTLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDbkUsT0FBTyxJQUFBLDZCQUFXLEVBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRDs7O0dBR0c7QUFDSSxLQUFLLFVBQVUsbUJBQW1CLENBQUMsR0FBZTtJQUN2RCxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsTUFBTSxTQUFTLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDcEUsT0FBTyxJQUFBLDZCQUFXLEVBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxHQUFjO0lBQ3JELE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFFRDs7O0dBR0c7QUFDSSxLQUFLLFVBQVUsa0JBQWtCLENBQUMsUUFBb0I7SUFDM0QsT0FBTyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNJLEtBQUssVUFBVSxpQkFBaUIsQ0FDckMsR0FBaUIsRUFDakIsU0FBaUI7SUFFakIsTUFBTSxRQUFRLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFBLHNCQUFRLEVBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSw0QkFBb0IsQ0FBQyxDQUFDO0lBQ3pFLE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBQ3RDLENBQUM7QUFFRDs7O0dBR0c7QUFDSSxLQUFLLFVBQVUsa0JBQWtCLENBQUMsTUFBc0I7SUFDN0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ2xELE1BQU0sTUFBTSxHQUFHLElBQUEsc0JBQVEsRUFBQyxVQUFVLENBQUMsQ0FBQztJQUNwQyxPQUFPLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xDLENBQUM7QUFFWSxRQUFBLG9CQUFvQixHQUFrQjtJQUNqRCxJQUFJLEVBQUosWUFBSTtJQUNKLE1BQU0sRUFBTixjQUFNO0lBQ04sT0FBTztJQUNQLHFCQUFxQjtJQUNyQixpQkFBaUI7SUFDakIsTUFBTTtJQUNOLE9BQU87SUFDUCxvQkFBb0I7SUFDcEIsa0JBQWtCO0lBQ2xCLG1CQUFtQjtJQUNuQixrQkFBa0I7SUFDbEIsbUJBQW1CO0lBQ25CLGlCQUFpQjtJQUNqQixXQUFXO0lBQ1gsZUFBZTtJQUNmLHNCQUFzQjtJQUN0QixnQkFBZ0I7SUFDaEIsZUFBZTtJQUNmLGtCQUFrQjtJQUNsQixpQkFBaUI7SUFDakIsa0JBQWtCO0lBQ2xCLGlCQUFpQjtJQUNqQixXQUFXO0lBQ1gsSUFBSTtJQUNKLFVBQVU7SUFDVixJQUFJO0lBQ0osaUJBQWlCO0lBQ2pCLE1BQU07Q0FDUCxDQUFDIn0=
|