jose 6.2.11 → 6.2.13
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 +2 -2
- package/dist/types/index.d.ts +1 -2
- package/dist/types/jwe/compact/decrypt.d.ts +9 -12
- package/dist/types/jwe/compact/encrypt.d.ts +14 -17
- package/dist/types/jwe/flattened/decrypt.d.ts +9 -12
- package/dist/types/jwe/flattened/encrypt.d.ts +17 -20
- package/dist/types/jwe/general/decrypt.d.ts +12 -17
- package/dist/types/jwe/general/encrypt.d.ts +19 -22
- package/dist/types/jwk/embedded.d.ts +3 -1
- package/dist/types/jwk/thumbprint.d.ts +4 -6
- package/dist/types/jwks/local.d.ts +5 -4
- package/dist/types/jwks/remote.d.ts +20 -21
- package/dist/types/jws/compact/sign.d.ts +7 -6
- package/dist/types/jws/compact/verify.d.ts +9 -12
- package/dist/types/jws/flattened/sign.d.ts +8 -7
- package/dist/types/jws/flattened/verify.d.ts +10 -12
- package/dist/types/jws/general/sign.d.ts +16 -17
- package/dist/types/jws/general/verify.d.ts +14 -18
- package/dist/types/jwt/decrypt.d.ts +15 -11
- package/dist/types/jwt/encrypt.d.ts +25 -23
- package/dist/types/jwt/sign.d.ts +4 -8
- package/dist/types/jwt/unsecured.d.ts +3 -7
- package/dist/types/jwt/verify.d.ts +12 -7
- package/dist/types/key/export.d.ts +6 -6
- package/dist/types/key/generate_key_pair.d.ts +9 -14
- package/dist/types/key/generate_secret.d.ts +10 -10
- package/dist/types/key/import.d.ts +21 -20
- package/dist/types/types.d.ts +217 -254
- package/dist/types/util/base64url.d.ts +7 -7
- package/dist/types/util/decode_jwt.d.ts +6 -1
- package/dist/types/util/decode_protected_header.d.ts +4 -3
- package/dist/types/util/errors.d.ts +30 -41
- package/dist/webapi/jwe/compact/decrypt.js +1 -2
- package/dist/webapi/jwe/compact/encrypt.js +9 -26
- package/dist/webapi/jwe/flattened/decrypt.js +3 -3
- package/dist/webapi/jwe/flattened/encrypt.js +11 -30
- package/dist/webapi/jwe/general/decrypt.js +6 -6
- package/dist/webapi/jwe/general/encrypt.js +36 -60
- package/dist/webapi/jwk/embedded.js +3 -4
- package/dist/webapi/jwk/thumbprint.js +11 -14
- package/dist/webapi/jwks/local.js +18 -11
- package/dist/webapi/jwks/remote.js +5 -5
- package/dist/webapi/jws/compact/sign.js +2 -4
- package/dist/webapi/jws/compact/verify.js +2 -2
- package/dist/webapi/jws/flattened/sign.js +8 -15
- package/dist/webapi/jws/flattened/verify.js +4 -14
- package/dist/webapi/jws/general/sign.js +6 -13
- package/dist/webapi/jws/general/verify.js +8 -10
- package/dist/webapi/jwt/decrypt.js +2 -3
- package/dist/webapi/jwt/encrypt.js +13 -27
- package/dist/webapi/jwt/sign.js +3 -3
- package/dist/webapi/jwt/unsecured.js +4 -5
- package/dist/webapi/jwt/verify.js +4 -4
- package/dist/webapi/key/export.js +12 -16
- package/dist/webapi/key/generate_key_pair.js +4 -13
- package/dist/webapi/key/generate_secret.js +5 -5
- package/dist/webapi/key/import.js +5 -9
- package/dist/webapi/lib/asn1.js +4 -6
- package/dist/webapi/lib/buffer_utils.js +39 -4
- package/dist/webapi/lib/content_encryption.js +29 -37
- package/dist/webapi/lib/deflate.js +9 -19
- package/dist/webapi/lib/jwe_algorithms.js +0 -4
- package/dist/webapi/lib/jwe_decrypt.js +30 -63
- package/dist/webapi/lib/jwe_encrypt.js +27 -60
- package/dist/webapi/lib/jws_algorithms.js +2 -2
- package/dist/webapi/lib/jws_sign.js +31 -45
- package/dist/webapi/lib/jws_verify.js +43 -48
- package/dist/webapi/lib/jwt_claims_set.js +45 -44
- package/dist/webapi/lib/key.js +122 -62
- package/dist/webapi/lib/key_management.js +57 -92
- package/dist/webapi/lib/{options.js → validate.js} +64 -3
- package/dist/webapi/util/base64url.js +5 -19
- package/dist/webapi/util/decode_jwt.js +13 -13
- package/dist/webapi/util/decode_protected_header.js +6 -6
- package/package.json +1 -1
- package/dist/webapi/lib/base64.js +0 -20
- package/dist/webapi/lib/crypto_key.js +0 -27
- package/dist/webapi/lib/helpers.js +0 -45
- package/dist/webapi/lib/invalid_key_input.js +0 -12
- package/dist/webapi/lib/is_key_like.js +0 -19
- package/dist/webapi/lib/jwk_metadata.js +0 -19
- package/dist/webapi/lib/jwk_to_key.js +0 -10
- package/dist/webapi/lib/key_options.js +0 -8
- package/dist/webapi/lib/signing.js +0 -22
- package/dist/webapi/lib/type_checks.js +0 -30
|
@@ -1,58 +1,44 @@
|
|
|
1
1
|
import { encode as b64u } from "../util/base64url.js";
|
|
2
|
-
import { sign } from "./signing.js";
|
|
3
2
|
import { jwsAlgorithm } from "./jws_algorithms.js";
|
|
4
|
-
import { isDisjoint } from "./
|
|
3
|
+
import { isDisjoint, serializeJoseHeader, validateB64, validateCrit, validateCritDuplicates, JWS_RECOGNIZED } from "./validate.js";
|
|
5
4
|
import { JWSInvalid } from "../util/errors.js";
|
|
6
|
-
import { concat, encode } from "./buffer_utils.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (protectedHeader
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function validateSignatureHeader(protectedHeader, joseHeader, crit) {
|
|
16
|
-
return validateCritDuplicates(JWSInvalid, protectedHeader), validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, crit, protectedHeader, joseHeader));
|
|
17
|
-
}
|
|
18
|
-
function signatureAlgorithm(joseHeader) {
|
|
19
|
-
const alg = joseHeader.alg;
|
|
20
|
-
if (typeof alg != "string" || !alg)
|
|
21
|
-
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
22
|
-
return jwsAlgorithm(alg);
|
|
23
|
-
}
|
|
24
|
-
async function signSignature(protectedHeader, payload, entry, key) {
|
|
25
|
-
const data = concat(encode(protectedHeader), encode("."), payload), k = await prepareKey(entry, key, "sign");
|
|
26
|
-
return b64u(await sign(entry, k, data));
|
|
27
|
-
}
|
|
28
|
-
async function createSignature(input, key, assertB64) {
|
|
29
|
-
let { protectedHeader, unprotectedHeader } = input, protectedHeaderString;
|
|
30
|
-
if ([protectedHeader, protectedHeaderString] = serializeProtectedHeader(protectedHeader), unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWSInvalid, unprotectedHeader)[0]), !protectedHeader && !unprotectedHeader)
|
|
5
|
+
import { concat, encode, encoder } from "./buffer_utils.js";
|
|
6
|
+
import { prepareKey, rawKey, checkModulusLength } from "./key.js";
|
|
7
|
+
async function createSignature(input, key, rejectUnencoded) {
|
|
8
|
+
let [payload, protectedHeader, unprotectedHeader, crit] = input, encodedProtectedHeader = "";
|
|
9
|
+
if (protectedHeader !== void 0) {
|
|
10
|
+
const normalized = serializeJoseHeader(JWSInvalid, protectedHeader);
|
|
11
|
+
protectedHeader = normalized[0], encodedProtectedHeader = b64u(normalized[1]);
|
|
12
|
+
}
|
|
13
|
+
if (unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWSInvalid, unprotectedHeader)[0]), !protectedHeader && !unprotectedHeader)
|
|
31
14
|
throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
|
|
32
15
|
if (!isDisjoint(protectedHeader, unprotectedHeader))
|
|
33
16
|
throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
34
|
-
const joseHeader = { ...protectedHeader, ...unprotectedHeader }
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
17
|
+
const joseHeader = { ...protectedHeader, ...unprotectedHeader };
|
|
18
|
+
validateCritDuplicates(JWSInvalid, protectedHeader);
|
|
19
|
+
const b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, crit, protectedHeader, joseHeader));
|
|
20
|
+
b64 || rejectUnencoded?.();
|
|
21
|
+
const { alg } = joseHeader;
|
|
22
|
+
if (typeof alg != "string" || !alg)
|
|
23
|
+
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
24
|
+
const entry = jwsAlgorithm(alg);
|
|
25
|
+
let encodedPayload = "", signingPayload = payload, signingInput;
|
|
38
26
|
if (b64) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
27
|
+
const encodedPayloadCache = input[4];
|
|
28
|
+
encodedPayloadCache ? (encodedPayload = encodedPayloadCache[0] ??= b64u(payload), signingPayload = encodedPayloadCache[1] ??= encode(encodedPayload)) : (encodedPayload = b64u(payload), signingInput = encoder.encode(`${encodedProtectedHeader}.${encodedPayload}`));
|
|
29
|
+
}
|
|
30
|
+
signingInput ??= concat(encode(encodedProtectedHeader), encode("."), signingPayload);
|
|
31
|
+
const signingKey = await rawKey(await prepareKey(entry, key, "sign"), entry.subtle, "sign");
|
|
32
|
+
entry.minRsaBits && checkModulusLength(entry.alg, signingKey);
|
|
43
33
|
const jws = {
|
|
44
|
-
signature: await
|
|
45
|
-
payload:
|
|
34
|
+
signature: b64u(new Uint8Array(await crypto.subtle.sign(entry.signing, signingKey, signingInput))),
|
|
35
|
+
payload: encodedPayload
|
|
46
36
|
};
|
|
47
|
-
return protectedHeader && (jws.protected =
|
|
37
|
+
return protectedHeader && (jws.protected = encodedProtectedHeader), unprotectedHeader && (jws.header = unprotectedHeader), [jws, b64];
|
|
48
38
|
}
|
|
49
|
-
async function createCompactSignature(payload,
|
|
50
|
-
const [protectedHeader,
|
|
51
|
-
|
|
52
|
-
throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
|
|
53
|
-
validateSignatureHeader(protectedHeader, protectedHeader, inputCrit) || rejectUnencoded();
|
|
54
|
-
const entry = signatureAlgorithm(protectedHeader), encodedPayload = b64u(payload), signature = await signSignature(protectedHeaderString, encode(encodedPayload), entry, key);
|
|
55
|
-
return `${protectedHeaderString}.${encodedPayload}.${signature}`;
|
|
39
|
+
async function createCompactSignature(payload, protectedHeader, crit, key, rejectUnencoded) {
|
|
40
|
+
const [jws] = await createSignature([payload, protectedHeader, void 0, crit], key, rejectUnencoded);
|
|
41
|
+
return `${jws.protected}.${jws.payload}.${jws.signature}`;
|
|
56
42
|
}
|
|
57
43
|
export {
|
|
58
44
|
createCompactSignature,
|
|
@@ -1,46 +1,30 @@
|
|
|
1
|
-
import { verify } from "./signing.js";
|
|
2
1
|
import { jwsAlgorithm } from "./jws_algorithms.js";
|
|
3
2
|
import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from "../util/errors.js";
|
|
4
3
|
import { concat, decoder, encoder, encode } from "./buffer_utils.js";
|
|
5
|
-
import { decodeBase64url,
|
|
6
|
-
import {
|
|
7
|
-
import { validateB64, validateCrit, validateAlgorithms, JWS_RECOGNIZED } from "./options.js";
|
|
8
|
-
import { prepareKey } from "./key.js";
|
|
4
|
+
import { decodeBase64url, encodeAsciiMember, parseJoseHeader, isDisjoint, isObject, validateB64, validateCrit, validateAlgorithms, JWS_RECOGNIZED } from "./validate.js";
|
|
5
|
+
import { prepareKey, rawKey, checkModulusLength } from "./key.js";
|
|
9
6
|
function snapshotJws(jws, sharedPayload) {
|
|
10
|
-
const
|
|
7
|
+
const encodedProtectedHeader = jws.protected, inputHeader = jws.header, header = isObject(inputHeader) ? { ...inputHeader } : inputHeader;
|
|
11
8
|
let payload = sharedPayload ? sharedPayload[0] : jws.payload;
|
|
12
9
|
!sharedPayload && payload instanceof Uint8Array && (payload = new Uint8Array(payload));
|
|
13
10
|
const signature = jws.signature, snapshot = { payload, signature };
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
if (encodedProtectedHeader !== void 0 && (snapshot.protected = encodedProtectedHeader), inputHeader !== void 0 && (snapshot.header = header), encodedProtectedHeader === void 0 && header === void 0)
|
|
12
|
+
throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members');
|
|
13
|
+
if (encodedProtectedHeader !== void 0 && typeof encodedProtectedHeader != "string")
|
|
14
|
+
throw new JWSInvalid("JWS Protected Header incorrect type");
|
|
15
|
+
if (payload === void 0)
|
|
16
|
+
throw new JWSInvalid("JWS Payload missing");
|
|
17
|
+
if (typeof signature != "string")
|
|
18
|
+
throw new JWSInvalid("JWS Signature missing or incorrect type");
|
|
19
|
+
if (header !== void 0 && !isObject(header))
|
|
20
|
+
throw new JWSInvalid("JWS Unprotected Header incorrect type");
|
|
21
|
+
return snapshot;
|
|
19
22
|
}
|
|
20
23
|
function prepareVerify(options) {
|
|
21
24
|
return [options && validateAlgorithms("algorithms", options.algorithms), options?.crit];
|
|
22
25
|
}
|
|
23
|
-
function parseProtectedHeader(
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
function validateJwsHeaders(parsedProt, joseHeader, shared) {
|
|
27
|
-
const b64 = validateB64(parsedProt, validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], parsedProt, joseHeader)), alg = joseHeader.alg;
|
|
28
|
-
if (typeof alg != "string" || !alg)
|
|
29
|
-
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
30
|
-
if (shared[0] && !shared[0].has(alg))
|
|
31
|
-
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
|
|
32
|
-
return [b64, alg];
|
|
33
|
-
}
|
|
34
|
-
function parseJwsHeaders(encodedProtected, header, shared, parsedProtected) {
|
|
35
|
-
const parsedProt = parseProtectedHeader(encodedProtected, parsedProtected);
|
|
36
|
-
let joseHeader;
|
|
37
|
-
if (header !== void 0) {
|
|
38
|
-
if (!isDisjoint(parsedProt, header))
|
|
39
|
-
throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
40
|
-
joseHeader = { ...parsedProt, ...header };
|
|
41
|
-
} else
|
|
42
|
-
joseHeader = parsedProt;
|
|
43
|
-
return [parsedProt, joseHeader, ...validateJwsHeaders(parsedProt, joseHeader, shared)];
|
|
26
|
+
function parseProtectedHeader(encodedProtectedHeader) {
|
|
27
|
+
return encodedProtectedHeader === void 0 ? {} : parseJoseHeader(encodedProtectedHeader, JWSInvalid, "JWS Protected Header is invalid");
|
|
44
28
|
}
|
|
45
29
|
function encodeJsonUnencodedPayload(payload) {
|
|
46
30
|
const invalid = /[\p{Cs}\p{Cn}]/u.exec(payload)?.[0];
|
|
@@ -51,27 +35,41 @@ function encodeJsonUnencodedPayload(payload) {
|
|
|
51
35
|
function encodeCompactUnencodedPayload(payload) {
|
|
52
36
|
try {
|
|
53
37
|
return encode(payload);
|
|
54
|
-
} catch {
|
|
55
|
-
throw new JWSInvalid("JWS Compact Serialization payload must use only ASCII characters"
|
|
38
|
+
} catch (cause) {
|
|
39
|
+
throw new JWSInvalid("JWS Compact Serialization payload must use only ASCII characters", {
|
|
40
|
+
cause
|
|
41
|
+
});
|
|
56
42
|
}
|
|
57
43
|
}
|
|
58
|
-
async function verifyPrepared(jws, shared, key, encodedProtected, parsedProt, alg, signingPayload) {
|
|
59
|
-
let resolvedKey = !1;
|
|
60
|
-
typeof key == "function" && (key = await key(parsedProt, jws), resolvedKey = !0);
|
|
61
|
-
const b64 = typeof signingPayload == "string", entry = jwsAlgorithm(alg), data = concat(encodedProtected !== void 0 ? encode(encodedProtected) : new Uint8Array(), encode("."), b64 ? shared[2] ??= encodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload), signature = decodeBase64url(jws.signature, "signature", JWSInvalid), k = await prepareKey(entry, key, "verify");
|
|
62
|
-
if (!await verify(entry, k, signature, data))
|
|
63
|
-
throw new JWSSignatureVerificationFailed();
|
|
64
|
-
return [b64 ? decodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload, parsedProt, b64, k, resolvedKey];
|
|
65
|
-
}
|
|
66
44
|
async function verifySignature(jws, shared, key, encodeUnencodedPayload, parsedProtected) {
|
|
67
|
-
const { protected:
|
|
45
|
+
const { protected: encodedProtectedHeader, header, payload: inputPayload } = jws, protectedHeader = parsedProtected ?? parseProtectedHeader(encodedProtectedHeader);
|
|
46
|
+
if (!isDisjoint(protectedHeader, header))
|
|
47
|
+
throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
48
|
+
const joseHeader = { ...protectedHeader, ...header }, b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], protectedHeader, joseHeader)), { alg } = joseHeader;
|
|
49
|
+
if (typeof alg != "string" || !alg)
|
|
50
|
+
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
51
|
+
if (shared[0] && !shared[0].has(alg))
|
|
52
|
+
throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
|
|
68
53
|
if (b64) {
|
|
69
54
|
if (typeof inputPayload != "string")
|
|
70
55
|
throw new JWSInvalid("JWS Payload must be a string");
|
|
71
56
|
} else if (typeof inputPayload != "string" && !(inputPayload instanceof Uint8Array))
|
|
72
57
|
throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
|
|
73
58
|
const signingPayload = b64 || typeof inputPayload != "string" ? inputPayload : encodeUnencodedPayload(inputPayload);
|
|
74
|
-
|
|
59
|
+
let resolvedKey = !1;
|
|
60
|
+
typeof key == "function" && (key = await key(protectedHeader, jws), resolvedKey = !0);
|
|
61
|
+
const entry = jwsAlgorithm(alg), signingInput = concat(encodedProtectedHeader !== void 0 ? encode(encodedProtectedHeader) : new Uint8Array(), encode("."), typeof signingPayload == "string" ? shared[2] ??= encodeAsciiMember(signingPayload, "payload", JWSInvalid) : signingPayload), signature = decodeBase64url(jws.signature, "signature", JWSInvalid), verificationKey = await prepareKey(entry, key, "verify"), cryptoKey = await rawKey(verificationKey, entry.subtle, "verify");
|
|
62
|
+
entry.minRsaBits && checkModulusLength(entry.alg, cryptoKey);
|
|
63
|
+
let verified = !1;
|
|
64
|
+
try {
|
|
65
|
+
verified = await crypto.subtle.verify(entry.signing, cryptoKey, signature, signingInput);
|
|
66
|
+
} catch (cause) {
|
|
67
|
+
throw new JWSSignatureVerificationFailed(void 0, { cause });
|
|
68
|
+
}
|
|
69
|
+
if (!verified)
|
|
70
|
+
throw new JWSSignatureVerificationFailed();
|
|
71
|
+
const result = { payload: typeof signingPayload == "string" ? decodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload };
|
|
72
|
+
return encodedProtectedHeader !== void 0 && (result.protectedHeader = protectedHeader), header !== void 0 && (result.unprotectedHeader = header), resolvedKey ? [{ ...result, key: verificationKey }, b64] : [result, b64];
|
|
75
73
|
}
|
|
76
74
|
async function verifyCompact(jws, shared, key) {
|
|
77
75
|
if (jws instanceof Uint8Array && (jws = decoder.decode(jws)), typeof jws != "string")
|
|
@@ -79,16 +77,13 @@ async function verifyCompact(jws, shared, key) {
|
|
|
79
77
|
const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
|
|
80
78
|
if (length !== 3)
|
|
81
79
|
throw new JWSInvalid("Invalid Compact JWS");
|
|
82
|
-
|
|
83
|
-
return verifyPrepared(compactJws, shared, key, protectedHeader, parsedProt, alg, signingPayload);
|
|
80
|
+
return verifySignature({ payload, protected: protectedHeader, signature }, shared, key, encodeCompactUnencodedPayload);
|
|
84
81
|
}
|
|
85
82
|
export {
|
|
86
83
|
encodeJsonUnencodedPayload,
|
|
87
|
-
parseJwsHeaders,
|
|
88
84
|
parseProtectedHeader,
|
|
89
85
|
prepareVerify,
|
|
90
86
|
snapshotJws,
|
|
91
87
|
verifyCompact,
|
|
92
|
-
verifyResult,
|
|
93
88
|
verifySignature
|
|
94
89
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from "../util/errors.js";
|
|
2
2
|
import { encoder, strictDecoder } from "./buffer_utils.js";
|
|
3
|
-
import { isObject } from "./
|
|
3
|
+
import { isObject } from "./validate.js";
|
|
4
4
|
const epoch = (date) => Math.floor(date.getTime() / 1e3), multipliers = {
|
|
5
5
|
s: 1,
|
|
6
6
|
m: 60,
|
|
@@ -16,8 +16,8 @@ function secs(str) {
|
|
|
16
16
|
typeof str != "string" && invalidDuration();
|
|
17
17
|
const matched = REGEX.exec(str);
|
|
18
18
|
(!matched || matched[4] && matched[1]) && invalidDuration();
|
|
19
|
-
const value = parseFloat(matched[2]),
|
|
20
|
-
return Number.isFinite(
|
|
19
|
+
const value = parseFloat(matched[2]), durationSeconds = Math.round(value * multipliers[matched[3][0].toLowerCase()]);
|
|
20
|
+
return Number.isFinite(durationSeconds) || invalidDuration(), matched[1] === "-" || matched[4] === "ago" ? -durationSeconds : durationSeconds;
|
|
21
21
|
}
|
|
22
22
|
function validateInput(label, input) {
|
|
23
23
|
if (!Number.isFinite(input))
|
|
@@ -39,34 +39,35 @@ const normalizeTyp = (value) => {
|
|
|
39
39
|
const normalized = value.toLowerCase();
|
|
40
40
|
return value.includes("/") ? normalized : `application/${normalized}`;
|
|
41
41
|
}, checkAudiencePresence = (audPayload, audOption) => typeof audPayload == "string" ? audOption.includes(audPayload) : Array.isArray(audPayload) ? audOption.some((aud) => audPayload.includes(aud)) : !1;
|
|
42
|
-
function validateNumericDate(
|
|
43
|
-
const value =
|
|
42
|
+
function validateNumericDate(claimsSet, claim, required = !1) {
|
|
43
|
+
const value = claimsSet[claim];
|
|
44
44
|
if (!(value === void 0 && !required)) {
|
|
45
45
|
if (typeof value != "number")
|
|
46
|
-
throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`,
|
|
46
|
+
throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`, claimsSet, claim, "invalid");
|
|
47
47
|
return value;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
function unexpectedClaim(
|
|
51
|
-
throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`,
|
|
50
|
+
function unexpectedClaim(claimsSet, claim) {
|
|
51
|
+
throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`, claimsSet, claim, checkFailed);
|
|
52
52
|
}
|
|
53
|
-
function validateClaimsSet(protectedHeader,
|
|
54
|
-
let
|
|
53
|
+
function validateClaimsSet(protectedHeader, claimsSetBytes, options = {}) {
|
|
54
|
+
let claimsSet;
|
|
55
55
|
try {
|
|
56
|
-
|
|
57
|
-
} catch {
|
|
56
|
+
claimsSet = JSON.parse(strictDecoder.decode(claimsSetBytes));
|
|
57
|
+
} catch (cause) {
|
|
58
|
+
throw new JWTInvalid("JWT Claims Set must be a top-level JSON object", { cause });
|
|
58
59
|
}
|
|
59
|
-
if (!isObject(
|
|
60
|
+
if (!isObject(claimsSet))
|
|
60
61
|
throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
|
|
61
62
|
const { typ } = options;
|
|
62
63
|
if (typ !== void 0 && (typeof protectedHeader.typ != "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ)))
|
|
63
|
-
throw new JWTClaimValidationFailed('unexpected "typ" JWT header value',
|
|
64
|
+
throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', claimsSet, "typ", checkFailed);
|
|
64
65
|
const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options, presenceCheck = [...requiredClaims];
|
|
65
66
|
maxTokenAge !== void 0 && presenceCheck.push("iat"), audience !== void 0 && presenceCheck.push("aud"), subject !== void 0 && presenceCheck.push("sub"), issuer !== void 0 && presenceCheck.push("iss");
|
|
66
67
|
for (const claim of new Set(presenceCheck.reverse()))
|
|
67
|
-
if (!Object.hasOwn(
|
|
68
|
-
throw new JWTClaimValidationFailed(`missing required "${claim}" claim`,
|
|
69
|
-
issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(
|
|
68
|
+
if (!Object.hasOwn(claimsSet, claim))
|
|
69
|
+
throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, claimsSet, claim, "missing");
|
|
70
|
+
issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(claimsSet.iss) && unexpectedClaim(claimsSet, "iss"), subject !== void 0 && claimsSet.sub !== subject && unexpectedClaim(claimsSet, "sub"), audience !== void 0 && !checkAudiencePresence(claimsSet.aud, typeof audience == "string" ? [audience] : audience) && unexpectedClaim(claimsSet, "aud");
|
|
70
71
|
const { clockTolerance } = options;
|
|
71
72
|
let tolerance = 0;
|
|
72
73
|
if (typeof clockTolerance == "string")
|
|
@@ -77,70 +78,70 @@ function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
|
|
|
77
78
|
tolerance = clockTolerance;
|
|
78
79
|
}
|
|
79
80
|
validateInput("clockTolerance option", tolerance);
|
|
80
|
-
const { currentDate } = options, now = validateInput("currentDate option", epoch(currentDate === void 0 ? /* @__PURE__ */ new Date() : currentDate)), iat = validateNumericDate(
|
|
81
|
+
const { currentDate } = options, now = validateInput("currentDate option", epoch(currentDate === void 0 ? /* @__PURE__ */ new Date() : currentDate)), iat = validateNumericDate(claimsSet, "iat", maxTokenAge !== void 0), nbf = validateNumericDate(claimsSet, "nbf");
|
|
81
82
|
if (nbf !== void 0 && nbf > now + tolerance)
|
|
82
|
-
throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed',
|
|
83
|
-
const exp = validateNumericDate(
|
|
83
|
+
throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', claimsSet, "nbf", checkFailed);
|
|
84
|
+
const exp = validateNumericDate(claimsSet, "exp");
|
|
84
85
|
if (exp !== void 0 && exp <= now - tolerance)
|
|
85
|
-
throw new JWTExpired('"exp" claim timestamp check failed',
|
|
86
|
+
throw new JWTExpired('"exp" claim timestamp check failed', claimsSet, "exp", checkFailed);
|
|
86
87
|
if (maxTokenAge !== void 0) {
|
|
87
88
|
const age = now - iat, max = validateInput("maxTokenAge option", typeof maxTokenAge == "number" ? maxTokenAge : secs(maxTokenAge));
|
|
88
89
|
if (age - tolerance > max)
|
|
89
|
-
throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)',
|
|
90
|
+
throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', claimsSet, "iat", checkFailed);
|
|
90
91
|
if (age < -tolerance)
|
|
91
|
-
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)',
|
|
92
|
+
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', claimsSet, "iat", checkFailed);
|
|
92
93
|
}
|
|
93
|
-
return
|
|
94
|
+
return claimsSet;
|
|
94
95
|
}
|
|
95
|
-
let
|
|
96
|
-
function
|
|
97
|
-
return
|
|
96
|
+
let producerClaimsSets;
|
|
97
|
+
function producerClaimsSet(producer) {
|
|
98
|
+
return producerClaimsSets.get(producer);
|
|
98
99
|
}
|
|
99
|
-
function
|
|
100
|
-
const
|
|
100
|
+
function jwtClaimsSetBytes(producer) {
|
|
101
|
+
const claimsSet = producerClaimsSet(producer);
|
|
101
102
|
for (const claim of ["iat", "nbf", "exp"]) {
|
|
102
|
-
const value =
|
|
103
|
+
const value = claimsSet[claim];
|
|
103
104
|
if (typeof value == "number" && !Number.isFinite(value))
|
|
104
105
|
throw new TypeError(`"${claim}" claim must be a finite number`);
|
|
105
106
|
}
|
|
106
|
-
return encoder.encode(JSON.stringify(
|
|
107
|
+
return encoder.encode(JSON.stringify(claimsSet));
|
|
107
108
|
}
|
|
108
109
|
function jwtClaim(producer, claim) {
|
|
109
|
-
return
|
|
110
|
+
return producerClaimsSet(producer)[claim];
|
|
110
111
|
}
|
|
111
112
|
class JWTClaimsBuilder {
|
|
112
|
-
constructor(
|
|
113
|
-
if (!isObject(
|
|
113
|
+
constructor(claimsSet = {}) {
|
|
114
|
+
if (!isObject(claimsSet))
|
|
114
115
|
throw new TypeError("JWT Claims Set MUST be an object");
|
|
115
|
-
(
|
|
116
|
+
(producerClaimsSets ||= /* @__PURE__ */ new WeakMap()).set(this, structuredClone(claimsSet));
|
|
116
117
|
}
|
|
117
118
|
setIssuer(value) {
|
|
118
|
-
return validateStringClaim("iss", value),
|
|
119
|
+
return validateStringClaim("iss", value), producerClaimsSet(this).iss = value, this;
|
|
119
120
|
}
|
|
120
121
|
setSubject(value) {
|
|
121
|
-
return validateStringClaim("sub", value),
|
|
122
|
+
return validateStringClaim("sub", value), producerClaimsSet(this).sub = value, this;
|
|
122
123
|
}
|
|
123
124
|
setAudience(value) {
|
|
124
|
-
return validateAudienceClaim(value),
|
|
125
|
+
return validateAudienceClaim(value), producerClaimsSet(this).aud = value, this;
|
|
125
126
|
}
|
|
126
127
|
setJti(value) {
|
|
127
|
-
return validateStringClaim("jti", value),
|
|
128
|
+
return validateStringClaim("jti", value), producerClaimsSet(this).jti = value, this;
|
|
128
129
|
}
|
|
129
130
|
setNotBefore(value) {
|
|
130
|
-
return
|
|
131
|
+
return producerClaimsSet(this).nbf = numericDate(value, "setNotBefore"), this;
|
|
131
132
|
}
|
|
132
133
|
setExpirationTime(value) {
|
|
133
|
-
return
|
|
134
|
+
return producerClaimsSet(this).exp = numericDate(value, "setExpirationTime"), this;
|
|
134
135
|
}
|
|
135
136
|
setIssuedAt(value) {
|
|
136
|
-
const
|
|
137
|
-
return value === void 0 ?
|
|
137
|
+
const claimsSet = producerClaimsSet(this);
|
|
138
|
+
return value === void 0 ? claimsSet.iat = epoch(/* @__PURE__ */ new Date()) : typeof value == "string" ? claimsSet.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value)) : claimsSet.iat = numericDate(value, "setIssuedAt"), this;
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
export {
|
|
141
142
|
JWTClaimsBuilder,
|
|
142
143
|
jwtClaim,
|
|
143
|
-
|
|
144
|
+
jwtClaimsSetBytes,
|
|
144
145
|
secs,
|
|
145
146
|
validateClaimsSet
|
|
146
147
|
};
|
package/dist/webapi/lib/key.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isKeyLike, isCryptoKey } from "./is_key_like.js";
|
|
3
|
-
import { isObject } from "./type_checks.js";
|
|
1
|
+
import { isObject } from "./validate.js";
|
|
4
2
|
import { decode } from "../util/base64url.js";
|
|
5
|
-
import {
|
|
6
|
-
import { normalizeJwk } from "./jwk_metadata.js";
|
|
3
|
+
import { JOSENotSupported } from "../util/errors.js";
|
|
7
4
|
const tag = (key) => key[Symbol.toStringTag], jwkMatchesOp = (entry, key, usage) => {
|
|
8
5
|
const { alg } = entry;
|
|
9
6
|
if (key.use !== void 0) {
|
|
@@ -19,35 +16,44 @@ const tag = (key) => key[Symbol.toStringTag], jwkMatchesOp = (entry, key, usage)
|
|
|
19
16
|
throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
|
|
20
17
|
}
|
|
21
18
|
};
|
|
22
|
-
function
|
|
23
|
-
const { alg, secret } = entry,
|
|
19
|
+
async function prepareKey(entry, key, usage) {
|
|
20
|
+
const { alg, secret } = entry, requiresPrivateKey = usage === "decrypt" || usage === "sign";
|
|
24
21
|
if (secret && key instanceof Uint8Array)
|
|
25
|
-
return
|
|
22
|
+
return key;
|
|
23
|
+
let normalized, keyObject;
|
|
26
24
|
if (isObject(key)) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (secret) {
|
|
37
|
-
if (key.type !== "secret")
|
|
38
|
-
throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
|
|
39
|
-
} else {
|
|
40
|
-
if (key.type === "secret")
|
|
41
|
-
throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
|
|
42
|
-
const expectedType = privateKey ? "private" : "public";
|
|
43
|
-
if ((key.type === "public" || key.type === "private") && key.type !== expectedType) {
|
|
44
|
-
const operation = usage === "sign" ? "signing" : usage === "verify" ? "verifying" : `${usage.slice(0, -1)}tion`;
|
|
45
|
-
throw new TypeError(`${tag(key)} instances for asymmetric algorithm ${operation} must be of type "${expectedType}"`);
|
|
25
|
+
if (normalized = normalizeJwk(key), typeof normalized.kty != "string")
|
|
26
|
+
throw invalidKeyType(alg, key, secret);
|
|
27
|
+
if (!(secret ? normalized.kty === "oct" && typeof normalized.k == "string" : normalized.kty !== "oct" && (requiresPrivateKey ? normalized.kty === "AKP" && typeof normalized.priv == "string" || typeof normalized.d == "string" : normalized.d === void 0 && normalized.priv === void 0)))
|
|
28
|
+
throw new TypeError(secret ? 'JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present' : `JSON Web Key for this operation must be a ${requiresPrivateKey ? "private" : "public"} JWK`);
|
|
29
|
+
if (jwkMatchesOp(entry, normalized, usage), normalized.kty === "oct")
|
|
30
|
+
return decode(normalized.k);
|
|
31
|
+
if (!Object.isFrozen(key)) {
|
|
32
|
+
const { key_ops } = key;
|
|
33
|
+
Array.isArray(key_ops) && Object.freeze(key_ops), Object.freeze(key);
|
|
46
34
|
}
|
|
35
|
+
} else {
|
|
36
|
+
if (!isKeyLike(key))
|
|
37
|
+
throw invalidKeyType(alg, key, secret);
|
|
38
|
+
const expectedType = secret ? "secret" : requiresPrivateKey ? "private" : "public";
|
|
39
|
+
if (key.type !== expectedType && (secret || ["secret", "public", "private"].includes(key.type)))
|
|
40
|
+
throw new TypeError(`${tag(key)} instances must be of type "${expectedType}" for the ${alg} algorithm`);
|
|
41
|
+
if (isCryptoKey(key))
|
|
42
|
+
return key;
|
|
43
|
+
if (keyObject = key, keyObject.type === "secret")
|
|
44
|
+
return keyObject.export();
|
|
45
|
+
}
|
|
46
|
+
cache ||= /* @__PURE__ */ new WeakMap();
|
|
47
|
+
const cacheKey = key;
|
|
48
|
+
let cached = cache.get(cacheKey);
|
|
49
|
+
if (cached?.[alg])
|
|
50
|
+
return cached[alg];
|
|
51
|
+
if (cached || cache.set(cacheKey, cached = {}), keyObject && typeof keyObject.toCryptoKey == "function") {
|
|
52
|
+
const isPublic = keyObject.type === "public", crv = nist[keyObject.asymmetricKeyDetails?.namedCurve], params = entry.resolve?.({ crv, asymmetricKeyType: keyObject.asymmetricKeyType }) ?? entry.subtle;
|
|
53
|
+
return cached[alg] = keyObject.toCryptoKey(params, isPublic, entry.usages[isPublic ? 0 : 1]);
|
|
47
54
|
}
|
|
48
|
-
return
|
|
55
|
+
return normalized ??= keyObject.export({ format: "jwk" }), normalized.alg = alg, cached[alg] = await jwkToKey(entry, normalized);
|
|
49
56
|
}
|
|
50
|
-
const BYTES = 0, CRYPTO = 1, KEYOBJECT = 2, JWK = 3;
|
|
51
57
|
let cache;
|
|
52
58
|
const nist = {
|
|
53
59
|
__proto__: null,
|
|
@@ -55,41 +61,95 @@ const nist = {
|
|
|
55
61
|
secp384r1: "P-384",
|
|
56
62
|
secp521r1: "P-521"
|
|
57
63
|
};
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return value && (entry ? entry[alg] = value : cache.set(key, { [alg]: value })), value ?? entry?.[alg];
|
|
64
|
+
function assertCryptoKey(key) {
|
|
65
|
+
if (!isCryptoKey(key))
|
|
66
|
+
throw new Error("CryptoKey instance expected");
|
|
62
67
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
async function prepareKey(entry, key, usage) {
|
|
71
|
-
const tagged = checkKeyType(entry, key, usage);
|
|
72
|
-
switch (tagged[0]) {
|
|
73
|
-
case BYTES:
|
|
74
|
-
case CRYPTO:
|
|
75
|
-
return tagged[1];
|
|
76
|
-
case JWK: {
|
|
77
|
-
const key2 = tagged[1], normalized = tagged[2];
|
|
78
|
-
if (normalized.kty === "oct")
|
|
79
|
-
return decode(normalized.k);
|
|
80
|
-
if (!Object.isFrozen(key2)) {
|
|
81
|
-
const { key_ops } = key2;
|
|
82
|
-
Array.isArray(key_ops) && Object.freeze(key_ops), Object.freeze(key2);
|
|
83
|
-
}
|
|
84
|
-
return handleJWK(key2, normalized, entry);
|
|
85
|
-
}
|
|
86
|
-
case KEYOBJECT: {
|
|
87
|
-
const keyObject = tagged[1];
|
|
88
|
-
return keyObject.type === "secret" ? keyObject.export() : "toCryptoKey" in keyObject && typeof keyObject.toCryptoKey == "function" ? handleKeyObject(keyObject, entry) : handleJWK(keyObject, keyObject.export({ format: "jwk" }), entry);
|
|
89
|
-
}
|
|
68
|
+
const isCryptoKey = (key) => {
|
|
69
|
+
if (key?.[Symbol.toStringTag] === "CryptoKey")
|
|
70
|
+
return !0;
|
|
71
|
+
try {
|
|
72
|
+
return key instanceof CryptoKey;
|
|
73
|
+
} catch {
|
|
74
|
+
return !1;
|
|
90
75
|
}
|
|
76
|
+
}, isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject", isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
|
|
77
|
+
function message(msg, actual, ...types) {
|
|
78
|
+
if (types.length > 2) {
|
|
79
|
+
const last = types.pop();
|
|
80
|
+
msg += `one of type ${types.join(", ")}, or ${last}.`;
|
|
81
|
+
} else types.length === 2 ? msg += `one of type ${types[0]} or ${types[1]}.` : msg += `of type ${types[0]}.`;
|
|
82
|
+
return actual == null ? msg += ` Received ${actual}` : typeof actual == "function" && actual.name ? msg += ` Received function ${actual.name}` : typeof actual == "object" && actual != null && actual.constructor?.name && (msg += ` Received an instance of ${actual.constructor.name}`), msg;
|
|
83
|
+
}
|
|
84
|
+
const invalidKeyInput = (actual, ...types) => message("Key must be ", actual, ...types);
|
|
85
|
+
function invalidKeyType(alg, actual, secret) {
|
|
86
|
+
const types = ["CryptoKey", "KeyObject", "JSON Web Key"];
|
|
87
|
+
return secret && types.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types));
|
|
88
|
+
}
|
|
89
|
+
const unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
90
|
+
function checkUsage(key, usage) {
|
|
91
|
+
if (usage && !key.usages.includes(usage))
|
|
92
|
+
throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
93
|
+
}
|
|
94
|
+
function checkModulusLength(alg, key) {
|
|
95
|
+
const { modulusLength } = key.algorithm;
|
|
96
|
+
if (typeof modulusLength != "number" || modulusLength < 2048)
|
|
97
|
+
throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
|
|
98
|
+
}
|
|
99
|
+
function checkCryptoKey(key, expected, usage) {
|
|
100
|
+
const algorithm = key.algorithm;
|
|
101
|
+
if (algorithm.name !== expected.name)
|
|
102
|
+
throw unusable(expected.name);
|
|
103
|
+
if (expected.hash && algorithm.hash?.name !== expected.hash)
|
|
104
|
+
throw unusable(expected.hash, "algorithm.hash");
|
|
105
|
+
if (expected.namedCurve && algorithm.namedCurve !== expected.namedCurve)
|
|
106
|
+
throw unusable(expected.namedCurve, "algorithm.namedCurve");
|
|
107
|
+
if (expected.length !== void 0 && algorithm.length !== expected.length)
|
|
108
|
+
throw unusable(expected.length, "algorithm.length");
|
|
109
|
+
checkUsage(key, usage);
|
|
110
|
+
}
|
|
111
|
+
function snapshotJwk(jwk) {
|
|
112
|
+
return { __proto__: null, ...jwk };
|
|
113
|
+
}
|
|
114
|
+
function normalizeJwk(jwk) {
|
|
115
|
+
const normalized = snapshotJwk(jwk);
|
|
116
|
+
if (normalized.ext !== void 0 && typeof normalized.ext != "boolean")
|
|
117
|
+
throw new TypeError('"ext" (Extractable) Parameter must be a boolean');
|
|
118
|
+
if (normalized.key_ops !== void 0) {
|
|
119
|
+
const value = normalized.key_ops, keyOps = Array.isArray(value) ? [...value] : void 0;
|
|
120
|
+
if (!keyOps || keyOps.some((operation) => typeof operation != "string") || new Set(keyOps).size !== keyOps.length)
|
|
121
|
+
throw new TypeError('"key_ops" (Key Operations) Parameter must be an array of unique strings');
|
|
122
|
+
normalized.key_ops = keyOps;
|
|
123
|
+
}
|
|
124
|
+
return normalized;
|
|
125
|
+
}
|
|
126
|
+
function validateExtractableOption(extractable) {
|
|
127
|
+
if (extractable !== void 0 && typeof extractable != "boolean")
|
|
128
|
+
throw new TypeError('"extractable" option must be a boolean');
|
|
129
|
+
return extractable;
|
|
130
|
+
}
|
|
131
|
+
async function jwkToKey(entry, jwk, extractable) {
|
|
132
|
+
if (!entry.kty.includes(jwk.kty))
|
|
133
|
+
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
134
|
+
const algorithm = entry.resolve?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle, isPrivate = !!(jwk.d || jwk.priv), keyData = { ...jwk, ext: extractable ?? jwk.ext };
|
|
135
|
+
return keyData.kty !== "AKP" && delete keyData.alg, delete keyData.use, crypto.subtle.importKey("jwk", keyData, algorithm, keyData.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
|
|
136
|
+
}
|
|
137
|
+
async function rawKey(key, expected, usage, extractable = !1) {
|
|
138
|
+
return key instanceof Uint8Array && (key = await crypto.subtle.importKey("raw", key, expected, extractable, [usage])), checkCryptoKey(key, expected, usage), key;
|
|
91
139
|
}
|
|
92
140
|
export {
|
|
93
|
-
|
|
94
|
-
|
|
141
|
+
assertCryptoKey,
|
|
142
|
+
checkCryptoKey,
|
|
143
|
+
checkModulusLength,
|
|
144
|
+
checkUsage,
|
|
145
|
+
invalidKeyInput,
|
|
146
|
+
isCryptoKey,
|
|
147
|
+
isKeyLike,
|
|
148
|
+
isKeyObject,
|
|
149
|
+
jwkToKey,
|
|
150
|
+
normalizeJwk,
|
|
151
|
+
prepareKey,
|
|
152
|
+
rawKey,
|
|
153
|
+
snapshotJwk,
|
|
154
|
+
validateExtractableOption
|
|
95
155
|
};
|