@opentdf/sdk 0.11.0 → 0.12.0-beta.112
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/README.md +17 -16
- package/dist/cjs/src/opentdf.js +21 -5
- package/dist/cjs/src/platform.js +23 -10
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/tdf3/src/crypto/core/ec.js +88 -0
- package/dist/cjs/tdf3/src/crypto/core/key-format.js +359 -0
- package/dist/cjs/tdf3/src/crypto/core/keys.js +85 -0
- package/dist/cjs/tdf3/src/crypto/core/rsa.js +120 -0
- package/dist/cjs/tdf3/src/crypto/core/signing.js +178 -0
- package/dist/cjs/tdf3/src/crypto/core/symmetric.js +205 -0
- package/dist/cjs/tdf3/src/crypto/index.js +69 -1051
- package/dist/types/src/opentdf.d.ts +2 -0
- package/dist/types/src/opentdf.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tdf3/src/crypto/core/ec.d.ts +11 -0
- package/dist/types/tdf3/src/crypto/core/ec.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/core/key-format.d.ts +41 -0
- package/dist/types/tdf3/src/crypto/core/key-format.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/core/keys.d.ts +27 -0
- package/dist/types/tdf3/src/crypto/core/keys.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/core/rsa.d.ts +35 -0
- package/dist/types/tdf3/src/crypto/core/rsa.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/core/signing.d.ts +10 -0
- package/dist/types/tdf3/src/crypto/core/signing.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/core/symmetric.d.ts +68 -0
- package/dist/types/tdf3/src/crypto/core/symmetric.d.ts.map +1 -0
- package/dist/types/tdf3/src/crypto/index.d.ts +11 -164
- package/dist/types/tdf3/src/crypto/index.d.ts.map +1 -1
- package/dist/web/src/opentdf.js +21 -5
- package/dist/web/src/platform.js +23 -10
- package/dist/web/src/version.js +1 -1
- package/dist/web/tdf3/src/crypto/core/ec.js +84 -0
- package/dist/web/tdf3/src/crypto/core/key-format.js +348 -0
- package/dist/web/tdf3/src/crypto/core/keys.js +78 -0
- package/dist/web/tdf3/src/crypto/core/rsa.js +112 -0
- package/dist/web/tdf3/src/crypto/core/signing.js +174 -0
- package/dist/web/tdf3/src/crypto/core/symmetric.js +192 -0
- package/dist/web/tdf3/src/crypto/index.js +13 -994
- package/package.json +1 -1
- package/src/opentdf.ts +22 -4
- package/src/platform.ts +23 -9
- package/src/version.ts +1 -1
- package/tdf3/src/crypto/core/ec.ts +118 -0
- package/tdf3/src/crypto/core/key-format.ts +420 -0
- package/tdf3/src/crypto/core/keys.ts +86 -0
- package/tdf3/src/crypto/core/rsa.ts +144 -0
- package/tdf3/src/crypto/core/signing.ts +214 -0
- package/tdf3/src/crypto/core/symmetric.ts +265 -0
- package/tdf3/src/crypto/index.ts +71 -1239
package/dist/web/src/platform.js
CHANGED
|
@@ -91,15 +91,28 @@ function createAuthInterceptor(authProvider) {
|
|
|
91
91
|
const url = new URL(req.url);
|
|
92
92
|
const pathOnly = url.pathname;
|
|
93
93
|
// Signs only the path of the url in the request
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
let token;
|
|
95
|
+
try {
|
|
96
|
+
token = await authProvider.withCreds({
|
|
97
|
+
url: pathOnly,
|
|
98
|
+
method: 'POST',
|
|
99
|
+
// Start with any headers Connect already has
|
|
100
|
+
headers: {
|
|
101
|
+
...Object.fromEntries(req.header.entries()),
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
+
if (msg.includes('public key') || msg.includes('updateClientPublicKey')) {
|
|
109
|
+
throw new Error('PlatformClient: DPoP key binding is not complete. ' +
|
|
110
|
+
'If you are using OpenTDF with PlatformClient, create OpenTDF first and ' +
|
|
111
|
+
'`await client.ready` before constructing PlatformClient. ' +
|
|
112
|
+
`Original error: ${msg}`);
|
|
113
|
+
}
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
103
116
|
Object.entries(token.headers).forEach(([key, value]) => {
|
|
104
117
|
req.header.set(key, value);
|
|
105
118
|
});
|
|
@@ -107,4 +120,4 @@ function createAuthInterceptor(authProvider) {
|
|
|
107
120
|
};
|
|
108
121
|
return authInterceptor;
|
|
109
122
|
}
|
|
110
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
123
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGxhdGZvcm0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0JBQStCO0FBQy9CLE9BQU8sS0FBSyxrQkFBa0IsTUFBTSx5QkFBeUIsQ0FBQztBQUM5RCxPQUFPLEtBQUssZUFBZSxNQUFNLHFCQUFxQixDQUFDO0FBRXZELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBR2pFLE9BQU8sRUFBVSxZQUFZLEVBQWUsTUFBTSxxQkFBcUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpRUFBaUUsQ0FBQztBQUNuRyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQUNwRixPQUFPLEVBQUUsb0JBQW9CLElBQUksc0JBQXNCLEVBQUUsTUFBTSxpREFBaUQsQ0FBQztBQUNqSCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxxREFBcUQsQ0FBQztBQUM5RixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLGdFQUFnRSxDQUFDO0FBQ2hILE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHNEQUFzRCxDQUFDO0FBQzVGLE9BQU8sRUFBRSxPQUFPLElBQUksaUJBQWlCLEVBQUUsTUFBTSxpREFBaUQsQ0FBQztBQUMvRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQztBQUNqRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxrRUFBa0UsQ0FBQztBQUM5RyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwwREFBMEQsQ0FBQztBQUNsRyxP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
|
package/dist/web/src/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Exposes the released version number of the `@opentdf/sdk` package
|
|
3
3
|
*/
|
|
4
|
-
export const version = '0.
|
|
4
|
+
export const version = '0.12.0'; // x-release-please-version
|
|
5
5
|
/**
|
|
6
6
|
* A string name used to label requests as coming from this library client.
|
|
7
7
|
*/
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { ConfigurationError } from '../../../../src/errors.js';
|
|
2
|
+
import { unwrapKey, wrapPrivateKey, wrapPublicKey, wrapSymmetricKey } from './keys.js';
|
|
3
|
+
/**
|
|
4
|
+
* Map ECCurve to Web Crypto named curve.
|
|
5
|
+
*/
|
|
6
|
+
function curveToNamedCurve(curve) {
|
|
7
|
+
switch (curve) {
|
|
8
|
+
case 'P-256':
|
|
9
|
+
return 'P-256';
|
|
10
|
+
case 'P-384':
|
|
11
|
+
return 'P-384';
|
|
12
|
+
case 'P-521':
|
|
13
|
+
return 'P-521';
|
|
14
|
+
default:
|
|
15
|
+
throw new ConfigurationError(`Unsupported curve: ${curve}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate an EC key pair for ECDH key agreement.
|
|
20
|
+
*/
|
|
21
|
+
export async function generateECKeyPair(curve = 'P-256') {
|
|
22
|
+
const namedCurve = curveToNamedCurve(curve);
|
|
23
|
+
// Generate key pair for ECDH key agreement
|
|
24
|
+
const keyPair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve }, true, [
|
|
25
|
+
'deriveBits',
|
|
26
|
+
]);
|
|
27
|
+
// Map to KeyAlgorithm literal type
|
|
28
|
+
let algorithm;
|
|
29
|
+
switch (namedCurve) {
|
|
30
|
+
case 'P-256':
|
|
31
|
+
algorithm = 'ec:secp256r1';
|
|
32
|
+
break;
|
|
33
|
+
case 'P-384':
|
|
34
|
+
algorithm = 'ec:secp384r1';
|
|
35
|
+
break;
|
|
36
|
+
case 'P-521':
|
|
37
|
+
algorithm = 'ec:secp521r1';
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
throw new ConfigurationError(`Unsupported curve: ${namedCurve}`);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
publicKey: wrapPublicKey(keyPair.publicKey, algorithm),
|
|
44
|
+
privateKey: wrapPrivateKey(keyPair.privateKey, algorithm),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Perform ECDH key agreement followed by HKDF key derivation.
|
|
49
|
+
* Returns opaque symmetric key for symmetric encryption.
|
|
50
|
+
*/
|
|
51
|
+
export async function deriveKeyFromECDH(privateKey, publicKey, hkdfParams) {
|
|
52
|
+
// Unwrap the internal CryptoKeys
|
|
53
|
+
const privateKeyCrypto = unwrapKey(privateKey);
|
|
54
|
+
const publicKeyCrypto = unwrapKey(publicKey);
|
|
55
|
+
// Get curve from key metadata
|
|
56
|
+
const curve = publicKey.curve;
|
|
57
|
+
if (!curve) {
|
|
58
|
+
throw new ConfigurationError('EC curve not found on public key');
|
|
59
|
+
}
|
|
60
|
+
// Determine bits based on curve
|
|
61
|
+
const curveBits = {
|
|
62
|
+
'P-256': 256,
|
|
63
|
+
'P-384': 384,
|
|
64
|
+
// P-521 derives 528 bits (66 bytes)
|
|
65
|
+
'P-521': 528,
|
|
66
|
+
};
|
|
67
|
+
const bits = curveBits[curve];
|
|
68
|
+
// Perform ECDH to get shared secret
|
|
69
|
+
const sharedSecret = await crypto.subtle.deriveBits({ name: 'ECDH', public: publicKeyCrypto }, privateKeyCrypto, bits);
|
|
70
|
+
// Import shared secret as HKDF key material
|
|
71
|
+
const hkdfKey = await crypto.subtle.importKey('raw', sharedSecret, 'HKDF', false, ['deriveKey']);
|
|
72
|
+
// Derive the final key using HKDF
|
|
73
|
+
const keyLength = hkdfParams.keyLength ?? 256;
|
|
74
|
+
const derivedKey = await crypto.subtle.deriveKey({
|
|
75
|
+
name: 'HKDF',
|
|
76
|
+
hash: hkdfParams.hash,
|
|
77
|
+
salt: hkdfParams.salt,
|
|
78
|
+
info: hkdfParams.info ?? new Uint8Array(0),
|
|
79
|
+
}, hkdfKey, { name: 'AES-GCM', length: keyLength }, true, ['encrypt', 'decrypt']);
|
|
80
|
+
// Export the derived key as raw bytes and wrap as SymmetricKey
|
|
81
|
+
const keyBytes = await crypto.subtle.exportKey('raw', derivedKey);
|
|
82
|
+
return wrapSymmetricKey(new Uint8Array(keyBytes));
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZGYzL3NyYy9jcnlwdG8vY29yZS9lYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFTQSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFdkY7O0dBRUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLEtBQWM7SUFDdkMsUUFBUSxLQUFLLEVBQUUsQ0FBQztRQUNkLEtBQUssT0FBTztZQUNWLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLEtBQUssT0FBTztZQUNWLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLEtBQUssT0FBTztZQUNWLE9BQU8sT0FBTyxDQUFDO1FBQ2pCO1lBQ0UsTUFBTSxJQUFJLGtCQUFrQixDQUFDLHNCQUFzQixLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGlCQUFpQixDQUFDLFFBQWlCLE9BQU87SUFDOUQsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFNUMsMkNBQTJDO0lBQzNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRTtRQUNsRixZQUFZO0tBQ2IsQ0FBQyxDQUFDO0lBRUgsbUNBQW1DO0lBQ25DLElBQUksU0FBdUIsQ0FBQztJQUM1QixRQUFRLFVBQVUsRUFBRSxDQUFDO1FBQ25CLEtBQUssT0FBTztZQUNWLFNBQVMsR0FBRyxjQUFjLENBQUM7WUFDM0IsTUFBTTtRQUNSLEtBQUssT0FBTztZQUNWLFNBQVMsR0FBRyxjQUFjLENBQUM7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
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { MIN_ASYMMETRIC_KEY_SIZE_BITS, } from '../declarations.js';
|
|
2
|
+
import { ConfigurationError } from '../../../../src/errors.js';
|
|
3
|
+
import { formatAsPem, removePemFormatting } from '../crypto-utils.js';
|
|
4
|
+
import { encodeArrayBuffer as hexEncode } from '../../../../src/encodings/hex.js';
|
|
5
|
+
import { decodeArrayBuffer as base64Decode } from '../../../../src/encodings/base64.js';
|
|
6
|
+
import { exportSPKI, importX509 } from 'jose';
|
|
7
|
+
import { guessAlgorithmName, guessCurveName, toJwsAlg, } from '../../../../src/crypto/pemPublicToCrypto.js';
|
|
8
|
+
import { unwrapKey, wrapPrivateKey, wrapPublicKey } from './keys.js';
|
|
9
|
+
import { rsaOaepSha1 } from './rsa.js';
|
|
10
|
+
/**
|
|
11
|
+
* Extract PEM public key from X.509 certificate or return PEM key as-is.
|
|
12
|
+
*/
|
|
13
|
+
export async function extractPublicKeyPem(certOrPem, jwaAlgorithm) {
|
|
14
|
+
// If it's a certificate, extract the public key
|
|
15
|
+
if (certOrPem.includes('-----BEGIN CERTIFICATE-----')) {
|
|
16
|
+
let alg = jwaAlgorithm;
|
|
17
|
+
if (!alg) {
|
|
18
|
+
// Auto-detect algorithm from certificate OIDs
|
|
19
|
+
const certBody = certOrPem.replace(/-----(BEGIN|END) CERTIFICATE-----|\s/g, '');
|
|
20
|
+
const certBytes = base64Decode(certBody);
|
|
21
|
+
const hex = hexEncode(certBytes);
|
|
22
|
+
alg = toJwsAlg(hex);
|
|
23
|
+
}
|
|
24
|
+
const cert = await importX509(certOrPem, alg, { extractable: true });
|
|
25
|
+
return exportSPKI(cert);
|
|
26
|
+
}
|
|
27
|
+
// If it's already a PEM public key, return as-is
|
|
28
|
+
if (certOrPem.includes('-----BEGIN PUBLIC KEY-----')) {
|
|
29
|
+
return certOrPem;
|
|
30
|
+
}
|
|
31
|
+
throw new ConfigurationError('Input must be a PEM-encoded certificate or public key');
|
|
32
|
+
}
|
|
33
|
+
const SUPPORTED_EC_CURVES = ['P-256', 'P-384', 'P-521'];
|
|
34
|
+
/**
|
|
35
|
+
* Decode base64url string and return byte length.
|
|
36
|
+
* Uses the existing base64 decoder which handles both standard and URL-safe encoding.
|
|
37
|
+
*/
|
|
38
|
+
function base64urlByteLength(base64url) {
|
|
39
|
+
// Add padding if needed (base64url omits padding)
|
|
40
|
+
const padding = (4 - (base64url.length % 4)) % 4;
|
|
41
|
+
const padded = base64url + '='.repeat(padding);
|
|
42
|
+
return base64Decode(padded).byteLength;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Extract EC curve from a public key by parsing ASN.1 OIDs.
|
|
46
|
+
* Reuses the existing guessCurveName function that checks for curve OIDs.
|
|
47
|
+
*/
|
|
48
|
+
function extractEcCurveFromPublicKey(keyData) {
|
|
49
|
+
// Convert to hex for OID parsing
|
|
50
|
+
const hexKey = hexEncode(keyData);
|
|
51
|
+
// Use existing OID parser (returns 'P-256', 'P-384', or 'P-521')
|
|
52
|
+
const curveName = guessCurveName(hexKey);
|
|
53
|
+
return curveName;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract RSA modulus bit length by importing key and exporting as JWK.
|
|
57
|
+
* Uses Web Crypto's built-in ASN.1 parsing for robustness.
|
|
58
|
+
*/
|
|
59
|
+
async function extractRsaModulusBitLength(keyData) {
|
|
60
|
+
const key = await crypto.subtle.importKey('spki', keyData, { name: 'RSA-OAEP', hash: 'SHA-256' }, true, ['encrypt']);
|
|
61
|
+
const jwk = await crypto.subtle.exportKey('jwk', key);
|
|
62
|
+
if (!jwk.n) {
|
|
63
|
+
throw new ConfigurationError('Invalid RSA key: missing modulus');
|
|
64
|
+
}
|
|
65
|
+
// JWK 'n' is base64url-encoded modulus
|
|
66
|
+
// Decode and count bytes, multiply by 8 for bits
|
|
67
|
+
return base64urlByteLength(jwk.n) * 8;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Import and validate a PEM public key, returning algorithm info.
|
|
71
|
+
* Uses JWK export for robust key parameter detection.
|
|
72
|
+
*/
|
|
73
|
+
export async function parsePublicKeyPem(pem) {
|
|
74
|
+
// First extract public key if it's a certificate
|
|
75
|
+
let publicKeyPem = pem;
|
|
76
|
+
if (pem.includes('-----BEGIN CERTIFICATE-----')) {
|
|
77
|
+
publicKeyPem = await extractPublicKeyPem(pem);
|
|
78
|
+
}
|
|
79
|
+
if (!publicKeyPem.includes('-----BEGIN PUBLIC KEY-----')) {
|
|
80
|
+
throw new ConfigurationError('Input must be a PEM-encoded public key or certificate');
|
|
81
|
+
}
|
|
82
|
+
const keyData = base64Decode(removePemFormatting(publicKeyPem));
|
|
83
|
+
// Try RSA first - use JWK export to get modulus size
|
|
84
|
+
try {
|
|
85
|
+
const modulusBits = await extractRsaModulusBitLength(keyData);
|
|
86
|
+
let algorithm;
|
|
87
|
+
if (modulusBits < MIN_ASYMMETRIC_KEY_SIZE_BITS) {
|
|
88
|
+
throw new ConfigurationError(`RSA key size ${modulusBits} bits is below the minimum of ${MIN_ASYMMETRIC_KEY_SIZE_BITS} bits`);
|
|
89
|
+
}
|
|
90
|
+
else if (modulusBits <= 2048) {
|
|
91
|
+
algorithm = 'rsa:2048';
|
|
92
|
+
}
|
|
93
|
+
else if (modulusBits <= 4096) {
|
|
94
|
+
algorithm = 'rsa:4096';
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
throw new ConfigurationError(`Unsupported RSA key size: ${modulusBits} bits`);
|
|
98
|
+
}
|
|
99
|
+
return { algorithm, pem: publicKeyPem };
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
// If it's our own ConfigurationError, rethrow
|
|
103
|
+
if (e instanceof ConfigurationError) {
|
|
104
|
+
throw e;
|
|
105
|
+
}
|
|
106
|
+
// Not an RSA key, try EC next
|
|
107
|
+
}
|
|
108
|
+
// Try EC - parse curve from OID
|
|
109
|
+
try {
|
|
110
|
+
const detectedCurve = extractEcCurveFromPublicKey(keyData);
|
|
111
|
+
const curveMap = {
|
|
112
|
+
'P-256': 'ec:secp256r1',
|
|
113
|
+
'P-384': 'ec:secp384r1',
|
|
114
|
+
'P-521': 'ec:secp521r1',
|
|
115
|
+
};
|
|
116
|
+
return { algorithm: curveMap[detectedCurve], pem: publicKeyPem };
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Not a valid EC key
|
|
120
|
+
}
|
|
121
|
+
throw new ConfigurationError('Unable to determine public key algorithm - unsupported key type');
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Convert a JWK (JSON Web Key) to PEM format.
|
|
125
|
+
*/
|
|
126
|
+
export async function jwkToPublicKeyPem(jwk) {
|
|
127
|
+
let key;
|
|
128
|
+
if (jwk.kty === 'RSA') {
|
|
129
|
+
// RSA key
|
|
130
|
+
key = await crypto.subtle.importKey('jwk', jwk, { name: 'RSA-OAEP', hash: 'SHA-256' }, true, [
|
|
131
|
+
'encrypt',
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
else if (jwk.kty === 'EC') {
|
|
135
|
+
// EC key
|
|
136
|
+
const crv = jwk.crv;
|
|
137
|
+
if (!crv || !['P-256', 'P-384', 'P-521'].includes(crv)) {
|
|
138
|
+
throw new ConfigurationError(`Unsupported EC curve: ${crv}`);
|
|
139
|
+
}
|
|
140
|
+
key = await crypto.subtle.importKey('jwk', jwk, { name: 'ECDH', namedCurve: crv }, true, []);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
throw new ConfigurationError(`Unsupported JWK key type: ${jwk.kty}`);
|
|
144
|
+
}
|
|
145
|
+
const spkiBuffer = await crypto.subtle.exportKey('spki', key);
|
|
146
|
+
return formatAsPem(spkiBuffer, 'PUBLIC KEY');
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Convert a PEM public key to JWK format.
|
|
150
|
+
* Returns only public key components (no private key data).
|
|
151
|
+
*/
|
|
152
|
+
export async function publicKeyPemToJwk(publicKeyPem) {
|
|
153
|
+
const keyDataBase64 = removePemFormatting(publicKeyPem);
|
|
154
|
+
const keyBuffer = base64Decode(keyDataBase64);
|
|
155
|
+
const hex = hexEncode(keyBuffer);
|
|
156
|
+
// Detect key type using OID
|
|
157
|
+
const algorithmName = guessAlgorithmName(hex);
|
|
158
|
+
if (algorithmName === 'ECDH' || algorithmName === 'ECDSA') {
|
|
159
|
+
// EC key - detect curve from OID
|
|
160
|
+
const namedCurve = guessCurveName(hex);
|
|
161
|
+
const key = await crypto.subtle.importKey('spki', keyBuffer, { name: 'ECDSA', namedCurve }, true, ['verify']);
|
|
162
|
+
const jwk = await crypto.subtle.exportKey('jwk', key);
|
|
163
|
+
// Return only public key components
|
|
164
|
+
const { kty, crv, x, y } = jwk;
|
|
165
|
+
return { kty, crv, x, y };
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// RSA key
|
|
169
|
+
const key = await crypto.subtle.importKey('spki', keyBuffer, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, true, ['verify']);
|
|
170
|
+
const jwk = await crypto.subtle.exportKey('jwk', key);
|
|
171
|
+
// Return only public key components
|
|
172
|
+
const { kty, e, n } = jwk;
|
|
173
|
+
return { kty, e, n };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Import a PEM public key as an opaque key.
|
|
178
|
+
*/
|
|
179
|
+
export async function importPublicKey(pem, options) {
|
|
180
|
+
const { usage = 'encrypt', extractable = true, algorithmHint } = options;
|
|
181
|
+
// Detect algorithm from PEM; also normalises certificates → plain SPKI PEM.
|
|
182
|
+
const keyInfo = await parsePublicKeyPem(pem);
|
|
183
|
+
const algorithm = algorithmHint || keyInfo.algorithm;
|
|
184
|
+
// Use keyInfo.pem (normalised SPKI) not the original pem, which may be a certificate.
|
|
185
|
+
// Passing raw X.509 DER bytes to crypto.subtle.importKey('spki') would throw DataError.
|
|
186
|
+
const keyData = removePemFormatting(keyInfo.pem);
|
|
187
|
+
const keyBuffer = base64Decode(keyData);
|
|
188
|
+
// Determine Web Crypto algorithm and usages based on key type and usage
|
|
189
|
+
let cryptoAlgorithm;
|
|
190
|
+
let keyUsages;
|
|
191
|
+
if (algorithm.startsWith('rsa:')) {
|
|
192
|
+
if (usage === 'encrypt') {
|
|
193
|
+
cryptoAlgorithm = rsaOaepSha1();
|
|
194
|
+
keyUsages = ['encrypt'];
|
|
195
|
+
}
|
|
196
|
+
else if (usage === 'sign') {
|
|
197
|
+
cryptoAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };
|
|
198
|
+
keyUsages = ['verify'];
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
throw new ConfigurationError('RSA keys only support usage: encrypt or sign');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else if (algorithm.startsWith('ec:')) {
|
|
205
|
+
const curve = algorithm.split(':')[1];
|
|
206
|
+
const namedCurve = curve === 'secp256r1'
|
|
207
|
+
? 'P-256'
|
|
208
|
+
: curve === 'secp384r1'
|
|
209
|
+
? 'P-384'
|
|
210
|
+
: curve === 'secp521r1'
|
|
211
|
+
? 'P-521'
|
|
212
|
+
: (() => {
|
|
213
|
+
throw new ConfigurationError(`Unsupported EC curve: ${curve}`);
|
|
214
|
+
})();
|
|
215
|
+
if (usage === 'derive') {
|
|
216
|
+
cryptoAlgorithm = { name: 'ECDH', namedCurve };
|
|
217
|
+
keyUsages = [];
|
|
218
|
+
}
|
|
219
|
+
else if (usage === 'sign') {
|
|
220
|
+
cryptoAlgorithm = { name: 'ECDSA', namedCurve };
|
|
221
|
+
keyUsages = ['verify'];
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
throw new ConfigurationError('EC keys only support usage: derive or sign');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
throw new ConfigurationError(`Unsupported algorithm: ${algorithm}`);
|
|
229
|
+
}
|
|
230
|
+
// Import as CryptoKey
|
|
231
|
+
const cryptoKey = await crypto.subtle.importKey('spki', keyBuffer, cryptoAlgorithm, extractable, keyUsages);
|
|
232
|
+
return wrapPublicKey(cryptoKey, algorithm);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Import a PEM private key as an opaque key.
|
|
236
|
+
*/
|
|
237
|
+
export async function importPrivateKey(pem, options) {
|
|
238
|
+
const { usage = 'encrypt', extractable = true, algorithmHint } = options;
|
|
239
|
+
// Detect algorithm from PEM structure (similar to public key detection)
|
|
240
|
+
// For now, use algorithmHint if provided, otherwise detect from key structure
|
|
241
|
+
let algorithm;
|
|
242
|
+
const keyData = removePemFormatting(pem);
|
|
243
|
+
const keyBuffer = base64Decode(keyData);
|
|
244
|
+
if (algorithmHint) {
|
|
245
|
+
algorithm = algorithmHint;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// PKCS#8 PrivateKeyInfo embeds the same AlgorithmIdentifier OIDs as SPKI,
|
|
249
|
+
// so guessAlgorithmName / guessCurveName work on private key bytes too.
|
|
250
|
+
const hex = hexEncode(keyBuffer);
|
|
251
|
+
const algorithmName = guessAlgorithmName(hex); // throws on unrecognised OID
|
|
252
|
+
if (algorithmName === 'ECDH' || algorithmName === 'ECDSA') {
|
|
253
|
+
const namedCurve = guessCurveName(hex);
|
|
254
|
+
const curveMap = {
|
|
255
|
+
'P-256': 'ec:secp256r1',
|
|
256
|
+
'P-384': 'ec:secp384r1',
|
|
257
|
+
'P-521': 'ec:secp521r1',
|
|
258
|
+
};
|
|
259
|
+
const mapped = curveMap[namedCurve];
|
|
260
|
+
if (!mapped)
|
|
261
|
+
throw new ConfigurationError(`Unsupported EC curve in private key: ${namedCurve}`);
|
|
262
|
+
algorithm = mapped;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
// RSA — determine key size by importing and reading modulus length from JWK
|
|
266
|
+
const tempKey = await crypto.subtle.importKey('pkcs8', keyBuffer, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, true, ['sign']);
|
|
267
|
+
const jwk = await crypto.subtle.exportKey('jwk', tempKey);
|
|
268
|
+
if (!jwk.n) {
|
|
269
|
+
throw new ConfigurationError('Invalid RSA private key: missing modulus');
|
|
270
|
+
}
|
|
271
|
+
const modulusBits = base64urlByteLength(jwk.n) * 8;
|
|
272
|
+
if (modulusBits < MIN_ASYMMETRIC_KEY_SIZE_BITS) {
|
|
273
|
+
throw new ConfigurationError(`RSA key size ${modulusBits} bits is below the minimum of ${MIN_ASYMMETRIC_KEY_SIZE_BITS} bits`);
|
|
274
|
+
}
|
|
275
|
+
algorithm = modulusBits <= 2048 ? 'rsa:2048' : 'rsa:4096';
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Determine Web Crypto algorithm and usages
|
|
279
|
+
let cryptoAlgorithm;
|
|
280
|
+
let keyUsages;
|
|
281
|
+
if (algorithm.startsWith('rsa:')) {
|
|
282
|
+
if (usage === 'encrypt') {
|
|
283
|
+
cryptoAlgorithm = rsaOaepSha1();
|
|
284
|
+
keyUsages = ['decrypt'];
|
|
285
|
+
}
|
|
286
|
+
else if (usage === 'sign') {
|
|
287
|
+
cryptoAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };
|
|
288
|
+
keyUsages = ['sign'];
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
throw new ConfigurationError('RSA keys only support usage: encrypt or sign');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
else if (algorithm.startsWith('ec:')) {
|
|
295
|
+
const curve = algorithm.split(':')[1];
|
|
296
|
+
const namedCurve = curve === 'secp256r1'
|
|
297
|
+
? 'P-256'
|
|
298
|
+
: curve === 'secp384r1'
|
|
299
|
+
? 'P-384'
|
|
300
|
+
: curve === 'secp521r1'
|
|
301
|
+
? 'P-521'
|
|
302
|
+
: (() => {
|
|
303
|
+
throw new ConfigurationError(`Unsupported EC curve: ${curve}`);
|
|
304
|
+
})();
|
|
305
|
+
if (usage === 'derive') {
|
|
306
|
+
cryptoAlgorithm = { name: 'ECDH', namedCurve };
|
|
307
|
+
keyUsages = ['deriveBits'];
|
|
308
|
+
}
|
|
309
|
+
else if (usage === 'sign') {
|
|
310
|
+
cryptoAlgorithm = { name: 'ECDSA', namedCurve };
|
|
311
|
+
keyUsages = ['sign'];
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
throw new ConfigurationError('EC keys only support usage: derive or sign');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
throw new ConfigurationError(`Unsupported algorithm: ${algorithm}`);
|
|
319
|
+
}
|
|
320
|
+
// Import as CryptoKey
|
|
321
|
+
const cryptoKey = await crypto.subtle.importKey('pkcs8', keyBuffer, cryptoAlgorithm, extractable, keyUsages);
|
|
322
|
+
return wrapPrivateKey(cryptoKey, algorithm);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Export an opaque public key to PEM format.
|
|
326
|
+
*/
|
|
327
|
+
export async function exportPublicKeyPem(key) {
|
|
328
|
+
const cryptoKey = unwrapKey(key);
|
|
329
|
+
const keyBuffer = await crypto.subtle.exportKey('spki', cryptoKey);
|
|
330
|
+
return formatAsPem(keyBuffer, 'PUBLIC KEY');
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Export an opaque private key to PEM format.
|
|
334
|
+
* ONLY USE FOR TESTING/DEVELOPMENT. Private keys should NOT be exportable in secure environments.
|
|
335
|
+
*/
|
|
336
|
+
export async function exportPrivateKeyPem(key) {
|
|
337
|
+
const cryptoKey = unwrapKey(key);
|
|
338
|
+
const keyBuffer = await crypto.subtle.exportKey('pkcs8', cryptoKey);
|
|
339
|
+
return formatAsPem(keyBuffer, 'PRIVATE KEY');
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Export an opaque public key to JWK format.
|
|
343
|
+
*/
|
|
344
|
+
export async function exportPublicKeyJwk(key) {
|
|
345
|
+
const cryptoKey = unwrapKey(key);
|
|
346
|
+
return await crypto.subtle.exportKey('jwk', cryptoKey);
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LWZvcm1hdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RkZjMvc3JjL2NyeXB0by9jb3JlL2tleS1mb3JtYXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLDRCQUE0QixHQUk3QixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RSxPQUFPLEVBQUUsaUJBQWlCLElBQUksU0FBUyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDbEYsT0FBTyxFQUFFLGlCQUFpQixJQUFJLFlBQVksRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3hGLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlDLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsY0FBYyxFQUNkLFFBQVEsR0FDVCxNQUFNLDZDQUE2QyxDQUFDO0FBQ3JELE9BQU8sRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNyRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRXZDOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxtQkFBbUIsQ0FDdkMsU0FBaUIsRUFDakIsWUFBcUI7SUFFckIsZ0RBQWdEO0lBQ2hELElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyw2QkFBNkIsQ0FBQyxFQUFFLENBQUM7UUFDdEQsSUFBSSxHQUFHLEdBQUcsWUFBWSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNULDhDQUE4QztZQUM5QyxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLHVDQUF1QyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2hGLE1B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
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap a CryptoKey as an opaque PublicKey.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export function wrapPublicKey(key, algorithm) {
|
|
6
|
+
const result = {
|
|
7
|
+
_brand: 'PublicKey',
|
|
8
|
+
algorithm,
|
|
9
|
+
_internal: key,
|
|
10
|
+
};
|
|
11
|
+
if (algorithm.startsWith('rsa:')) {
|
|
12
|
+
result.modulusBits = parseInt(algorithm.split(':')[1], 10);
|
|
13
|
+
}
|
|
14
|
+
else if (algorithm.startsWith('ec:')) {
|
|
15
|
+
const curvePart = algorithm.split(':')[1];
|
|
16
|
+
result.curve =
|
|
17
|
+
curvePart === 'secp256r1'
|
|
18
|
+
? 'P-256'
|
|
19
|
+
: curvePart === 'secp384r1'
|
|
20
|
+
? 'P-384'
|
|
21
|
+
: curvePart === 'secp521r1'
|
|
22
|
+
? 'P-521'
|
|
23
|
+
: undefined;
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wrap a CryptoKey as an opaque PrivateKey.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export function wrapPrivateKey(key, algorithm) {
|
|
32
|
+
const result = {
|
|
33
|
+
_brand: 'PrivateKey',
|
|
34
|
+
algorithm,
|
|
35
|
+
_internal: key,
|
|
36
|
+
};
|
|
37
|
+
if (algorithm.startsWith('rsa:')) {
|
|
38
|
+
result.modulusBits = parseInt(algorithm.split(':')[1], 10);
|
|
39
|
+
}
|
|
40
|
+
else if (algorithm.startsWith('ec:')) {
|
|
41
|
+
const curvePart = algorithm.split(':')[1];
|
|
42
|
+
result.curve =
|
|
43
|
+
curvePart === 'secp256r1'
|
|
44
|
+
? 'P-256'
|
|
45
|
+
: curvePart === 'secp384r1'
|
|
46
|
+
? 'P-384'
|
|
47
|
+
: curvePart === 'secp521r1'
|
|
48
|
+
? 'P-521'
|
|
49
|
+
: undefined;
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Unwrap an opaque key to get the internal CryptoKey.
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export function unwrapKey(key) {
|
|
58
|
+
return key._internal;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Wrap raw key bytes as an opaque SymmetricKey.
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
export function wrapSymmetricKey(keyBytes) {
|
|
65
|
+
return {
|
|
66
|
+
_brand: 'SymmetricKey',
|
|
67
|
+
length: keyBytes.length * 8, // bits
|
|
68
|
+
_internal: keyBytes,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Unwrap an opaque SymmetricKey to get raw bytes.
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export function unwrapSymmetricKey(key) {
|
|
76
|
+
return key._internal;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RkZjMvc3JjL2NyeXB0by9jb3JlL2tleXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBT0E7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxHQUFjLEVBQUUsU0FBdUI7SUFDbkUsTUFBTSxNQUFNLEdBQVE7UUFDbEIsTUFBTSxFQUFFLFdBQVc7UUFDbkIsU0FBUztRQUNULFNBQVMsRUFBRSxHQUFHO0tBQ2YsQ0FBQztJQUNGLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztTQUFNLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLEtBQUs7WUFDVixTQUFTLEtBQUssV0FBVztnQkFDdkIsQ0FBQyxDQUFDLE9BQU87Z0JBQ1QsQ0FBQyxDQUFDLFNBQVMsS0FBSyxXQUFXO29CQUN6QixDQUFDLENBQUMsT0FBTztvQkFDVCxDQUFDLENBQUMsU0FBUyxLQUFLLFdBQVc7d0JBQ3pCLENBQUMsQ0FBQyxPQUFPO3dCQUNULENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDdEIsQ0FBQztJQUNELE9BQU8sTUFBbUIsQ0FBQztBQUM3QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxHQUFjLEVBQUUsU0FBdUI7SUFDcEUsTUFBTSxNQUFNLEdBQVE7UUFDbEIsTUFBTSxFQUFFLFlBQVk7UUFDcEIsU0FBUztRQUNULFNBQVMsRUFBRSxHQUFHO0tBQ2YsQ0FBQztJQUNGLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztTQUFNLElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLEtBQUs7WUFDVixTQUFTLEtBQUssV0FBVztnQkFDdkIsQ0FBQyxDQUFDLE9BQU87Z0JBQ1QsQ0FBQyxDQUFDLFNBQVMsS0FBSyxXQUFXO29CQUN6QixDQUFDLENBQUMsT0FBTztvQkFDVCxDQUFDLENBQUMsU0FBUyxLQUFLLFdBQVc7d0JBQ3pCLENBQUMsQ0FBQyxPQUFPO3dCQUNULENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDdEIsQ0FBQztJQUNELE9BQU8sTUFBb0IsQ0FBQztBQUM5QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FBQyxHQUEyQjtJQUNuRCxPQUFRLEdBQVcsQ0FBQyxTQUFTLENBQUM7QUFDaEMsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxRQUFvQjtJQUNuRCxPQUFPO1FBQ0wsTUFBTSxFQUFFLGNBQWM7UUFDdEIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLE9BQU87UUFDcEMsU0FBUyxFQUFFLFFBQVE7S0FDSixDQUFDO0FBQ3BCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsR0FBaUI7SUFDbEQsT0FBUSxHQUFXLENBQUMsU0FBUyxDQUFDO0FBQ2hDLENBQUMifQ==
|