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,19 +1,22 @@
|
|
|
1
|
-
import { jwkToKey } from "../lib/
|
|
1
|
+
import { jwkToKey, snapshotJwk } from "../lib/key.js";
|
|
2
2
|
import { JWS } from "../lib/jws_algorithms.js";
|
|
3
3
|
import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys } from "../util/errors.js";
|
|
4
|
-
import { isJwkSet } from "../lib/
|
|
5
|
-
import { snapshotJwk } from "../lib/jwk_metadata.js";
|
|
4
|
+
import { isJwkSet } from "../lib/validate.js";
|
|
6
5
|
function isUsableJWK(jwk, entry, alg, kid) {
|
|
7
|
-
const { kty, key_ops, ext, kid: jwkKid, alg: jwkAlg, use, crv } =
|
|
6
|
+
const { kty, key_ops: keyOps, ext, kid: jwkKid, alg: jwkAlg, use, crv } = jwk;
|
|
8
7
|
return (ext === void 0 || typeof ext == "boolean") && (keyOps === void 0 || Array.isArray(keyOps) && keyOps.every((operation, index) => typeof operation == "string" && keyOps.indexOf(operation) === index) && keyOps.includes("verify")) && entry.kty.includes(kty) && (kid === void 0 || typeof kid == "string" && kid === jwkKid) && (jwkAlg === void 0 ? kty !== "AKP" : alg === jwkAlg) && (use === void 0 || use === "sig") && (!entry.crv || crv === entry.crv);
|
|
9
8
|
}
|
|
10
9
|
async function importWithAlgCache(cache, jwk, entry) {
|
|
11
10
|
const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk), { alg } = entry;
|
|
12
11
|
if (cached[alg] === void 0) {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const pending = jwkToKey(entry, jwk, !0).then((key) => {
|
|
13
|
+
if (key.type !== "public")
|
|
14
|
+
throw new JWKSInvalid("JSON Web Key Set members must be public keys");
|
|
15
|
+
return cached[alg] = key, key;
|
|
16
|
+
}).catch((error) => {
|
|
17
|
+
throw cached[alg] === pending && delete cached[alg], error;
|
|
18
|
+
});
|
|
19
|
+
cached[alg] = pending;
|
|
17
20
|
}
|
|
18
21
|
return cached[alg];
|
|
19
22
|
}
|
|
@@ -21,16 +24,20 @@ function createLocalJWKSet(jwks) {
|
|
|
21
24
|
let snapshot;
|
|
22
25
|
try {
|
|
23
26
|
snapshot = structuredClone(jwks);
|
|
24
|
-
} catch {
|
|
27
|
+
} catch (cause) {
|
|
28
|
+
throw new JWKSInvalid("JSON Web Key Set malformed", { cause });
|
|
25
29
|
}
|
|
26
30
|
if (!isJwkSet(snapshot))
|
|
27
31
|
throw new JWKSInvalid("JSON Web Key Set malformed");
|
|
28
|
-
const
|
|
32
|
+
const metadata = snapshot.keys.map((jwk) => {
|
|
33
|
+
const normalized = snapshotJwk(jwk);
|
|
34
|
+
return Array.isArray(normalized.key_ops) && (normalized.key_ops = [...normalized.key_ops]), normalized;
|
|
35
|
+
}), cached = /* @__PURE__ */ new WeakMap();
|
|
29
36
|
return Object.defineProperty(async (protectedHeader, token) => {
|
|
30
37
|
const { alg, kid } = { ...protectedHeader, ...token?.header }, entry = typeof alg == "string" ? JWS[alg] : void 0;
|
|
31
38
|
if (!entry || entry.secret)
|
|
32
39
|
throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
|
|
33
|
-
const candidates = snapshot.keys.filter((
|
|
40
|
+
const candidates = snapshot.keys.filter((_, index) => isUsableJWK(metadata[index], entry, alg, kid)), { 0: jwk, length } = candidates;
|
|
34
41
|
if (!length)
|
|
35
42
|
throw new JWKSNoMatchingKey();
|
|
36
43
|
if (length !== 1) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from "../util/errors.js";
|
|
2
2
|
import { createLocalJWKSet } from "./local.js";
|
|
3
|
-
import { isJwkSet } from "../lib/
|
|
3
|
+
import { isJwkSet } from "../lib/validate.js";
|
|
4
4
|
function isCloudflareWorkers() {
|
|
5
5
|
return typeof WebSocketPair < "u" || typeof navigator < "u" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime < "u" && EdgeRuntime === "vercel";
|
|
6
6
|
}
|
|
7
7
|
let USER_AGENT;
|
|
8
|
-
(typeof navigator > "u" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) && (USER_AGENT = "jose/v6.2.
|
|
8
|
+
(typeof navigator > "u" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) && (USER_AGENT = "jose/v6.2.13");
|
|
9
9
|
const customFetch = /* @__PURE__ */ Symbol();
|
|
10
10
|
async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
|
|
11
11
|
const response = await fetchImpl(url, {
|
|
@@ -14,14 +14,14 @@ async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
|
|
|
14
14
|
redirect: "manual",
|
|
15
15
|
headers
|
|
16
16
|
}).catch((err) => {
|
|
17
|
-
throw err.name === "TimeoutError" ? new JWKSTimeout() : err;
|
|
17
|
+
throw err.name === "TimeoutError" ? new JWKSTimeout(void 0, { cause: err }) : err;
|
|
18
18
|
});
|
|
19
19
|
if (response.status !== 200)
|
|
20
20
|
throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response");
|
|
21
21
|
try {
|
|
22
22
|
return await response.json();
|
|
23
|
-
} catch {
|
|
24
|
-
throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON");
|
|
23
|
+
} catch (cause) {
|
|
24
|
+
throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON", { cause });
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
const jwksCache = /* @__PURE__ */ Symbol();
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { createCompactSignature } from "../../lib/jws_sign.js";
|
|
2
|
-
import { assertNotSet } from "../../lib/
|
|
2
|
+
import { assertNotSet, assertUint8Array } from "../../lib/validate.js";
|
|
3
3
|
class CompactSign {
|
|
4
4
|
#payload;
|
|
5
5
|
#protectedHeader;
|
|
6
6
|
constructor(payload) {
|
|
7
|
-
|
|
8
|
-
throw new TypeError("payload must be an instance of Uint8Array");
|
|
9
|
-
this.#payload = payload;
|
|
7
|
+
assertUint8Array(payload, "payload"), this.#payload = payload;
|
|
10
8
|
}
|
|
11
9
|
setProtectedHeader(protectedHeader) {
|
|
12
10
|
return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { prepareVerify, verifyCompact } from "../../lib/jws_verify.js";
|
|
2
2
|
async function compactVerify(jws, key, options) {
|
|
3
|
-
const
|
|
4
|
-
return
|
|
3
|
+
const [result] = await verifyCompact(jws, prepareVerify(options), key);
|
|
4
|
+
return result;
|
|
5
5
|
}
|
|
6
6
|
export {
|
|
7
7
|
compactVerify
|
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { createSignature } from "../../lib/jws_sign.js";
|
|
2
|
-
import { assertNotSet } from "../../lib/
|
|
2
|
+
import { assertNotSet, assertUint8Array } from "../../lib/validate.js";
|
|
3
3
|
class FlattenedSign {
|
|
4
|
-
#
|
|
5
|
-
#protectedHeader;
|
|
6
|
-
#unprotectedHeader;
|
|
4
|
+
#input;
|
|
7
5
|
constructor(payload) {
|
|
8
|
-
|
|
9
|
-
throw new TypeError("payload must be an instance of Uint8Array");
|
|
10
|
-
this.#payload = payload;
|
|
6
|
+
assertUint8Array(payload, "payload"), this.#input = [payload];
|
|
11
7
|
}
|
|
12
8
|
setProtectedHeader(protectedHeader) {
|
|
13
|
-
return assertNotSet(this.#
|
|
9
|
+
return assertNotSet(this.#input[1], "setProtectedHeader"), this.#input[1] = protectedHeader, this;
|
|
14
10
|
}
|
|
15
11
|
setUnprotectedHeader(unprotectedHeader) {
|
|
16
|
-
return assertNotSet(this.#
|
|
12
|
+
return assertNotSet(this.#input[2], "setUnprotectedHeader"), this.#input[2] = unprotectedHeader, this;
|
|
17
13
|
}
|
|
18
14
|
async sign(key, options) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
unprotectedHeader: this.#unprotectedHeader,
|
|
23
|
-
crit: options?.crit
|
|
24
|
-
}, key);
|
|
15
|
+
const input = [...this.#input];
|
|
16
|
+
input[3] = options?.crit;
|
|
17
|
+
const [jws] = await createSignature(input, key);
|
|
25
18
|
return jws;
|
|
26
19
|
}
|
|
27
20
|
}
|
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
import { JWSInvalid } from "../../util/errors.js";
|
|
2
|
-
import { isObject } from "../../lib/
|
|
3
|
-
import { encodeJsonUnencodedPayload, prepareVerify, snapshotJws, verifySignature
|
|
2
|
+
import { isObject } from "../../lib/validate.js";
|
|
3
|
+
import { encodeJsonUnencodedPayload, prepareVerify, snapshotJws, verifySignature } from "../../lib/jws_verify.js";
|
|
4
4
|
async function flattenedVerify(jws, key, options) {
|
|
5
5
|
if (!isObject(jws))
|
|
6
6
|
throw new JWSInvalid("Flattened JWS must be an object");
|
|
7
|
-
const snapshot = snapshotJws(jws);
|
|
8
|
-
|
|
9
|
-
throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members');
|
|
10
|
-
if (snapshot.protected !== void 0 && typeof snapshot.protected != "string")
|
|
11
|
-
throw new JWSInvalid("JWS Protected Header incorrect type");
|
|
12
|
-
if (snapshot.payload === void 0)
|
|
13
|
-
throw new JWSInvalid("JWS Payload missing");
|
|
14
|
-
if (typeof snapshot.signature != "string")
|
|
15
|
-
throw new JWSInvalid("JWS Signature missing or incorrect type");
|
|
16
|
-
if (snapshot.header !== void 0 && !isObject(snapshot.header))
|
|
17
|
-
throw new JWSInvalid("JWS Unprotected Header incorrect type");
|
|
18
|
-
return verifyResult(snapshot, await verifySignature(snapshot, prepareVerify(options), key, encodeJsonUnencodedPayload));
|
|
7
|
+
const snapshot = snapshotJws(jws), [result] = await verifySignature(snapshot, prepareVerify(options), key, encodeJsonUnencodedPayload);
|
|
8
|
+
return result;
|
|
19
9
|
}
|
|
20
10
|
export {
|
|
21
11
|
flattenedVerify
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createSignature } from "../../lib/jws_sign.js";
|
|
2
2
|
import { JWSInvalid } from "../../util/errors.js";
|
|
3
|
-
import { assertNotSet } from "../../lib/
|
|
3
|
+
import { assertNotSet, assertUint8Array } from "../../lib/validate.js";
|
|
4
4
|
class IndividualSignature {
|
|
5
5
|
#parent;
|
|
6
6
|
state;
|
|
@@ -36,26 +36,19 @@ class GeneralSign {
|
|
|
36
36
|
async sign() {
|
|
37
37
|
if (!this.#signatures.length)
|
|
38
38
|
throw new JWSInvalid("at least one signature must be added");
|
|
39
|
-
|
|
40
|
-
throw new TypeError("payload must be an instance of Uint8Array");
|
|
39
|
+
assertUint8Array(this.#payload, "payload");
|
|
41
40
|
const jws = {
|
|
42
41
|
signatures: [],
|
|
43
42
|
payload: ""
|
|
44
|
-
},
|
|
43
|
+
}, encodedPayloadCache = [];
|
|
45
44
|
let b64;
|
|
46
|
-
for (
|
|
47
|
-
const
|
|
48
|
-
payload: this.#payload,
|
|
49
|
-
protectedHeader,
|
|
50
|
-
unprotectedHeader,
|
|
51
|
-
crit,
|
|
52
|
-
encoded
|
|
53
|
-
}, key);
|
|
45
|
+
for (const signature of this.#signatures) {
|
|
46
|
+
const [protectedHeader, unprotectedHeader, key, crit] = signature.state, [{ payload, ...signatureMembers }, signatureB64] = await createSignature([this.#payload, protectedHeader, unprotectedHeader, crit, encodedPayloadCache], key);
|
|
54
47
|
if (b64 === void 0)
|
|
55
48
|
b64 = signatureB64, jws.payload = payload;
|
|
56
49
|
else if (b64 !== signatureB64)
|
|
57
50
|
throw new JWSInvalid("inconsistent use of JWS Unencoded Payload (RFC7797)");
|
|
58
|
-
jws.signatures.push(
|
|
51
|
+
jws.signatures.push(signatureMembers);
|
|
59
52
|
}
|
|
60
53
|
return jws;
|
|
61
54
|
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { encodeJsonUnencodedPayload, parseProtectedHeader, prepareVerify, snapshotJws, verifySignature
|
|
1
|
+
import { encodeJsonUnencodedPayload, parseProtectedHeader, prepareVerify, snapshotJws, verifySignature } from "../../lib/jws_verify.js";
|
|
2
2
|
import { JWSInvalid, JWSSignatureVerificationFailed } from "../../util/errors.js";
|
|
3
|
-
import { isObject } from "../../lib/
|
|
3
|
+
import { isObject } from "../../lib/validate.js";
|
|
4
4
|
function snapshotSignature(signature, payload) {
|
|
5
5
|
try {
|
|
6
|
-
const jws = snapshotJws(signature, [payload]),
|
|
7
|
-
if (encodedProtected === void 0 && header === void 0 || encodedProtected !== void 0 && typeof encodedProtected != "string" || typeof encodedSignature != "string" || header !== void 0 && !isObject(header))
|
|
8
|
-
return;
|
|
9
|
-
const protectedHeader = parseProtectedHeader(encodedProtected), { b64, crit } = protectedHeader;
|
|
6
|
+
const jws = snapshotJws(signature, [payload]), protectedHeader = parseProtectedHeader(jws.protected), { b64, crit } = protectedHeader;
|
|
10
7
|
return [
|
|
11
8
|
jws,
|
|
12
9
|
protectedHeader,
|
|
@@ -34,13 +31,14 @@ async function generalVerify(jws, key, options) {
|
|
|
34
31
|
throw new JWSSignatureVerificationFailed();
|
|
35
32
|
}
|
|
36
33
|
const payload = inputPayload instanceof Uint8Array ? new Uint8Array(inputPayload) : inputPayload, candidates = signatureEntries.map((signature) => snapshotSignature(signature, payload)).filter((candidate) => candidate !== void 0);
|
|
37
|
-
let
|
|
38
|
-
for (const [, ,
|
|
39
|
-
if (
|
|
34
|
+
let payloadEncodings = 0;
|
|
35
|
+
for (const [, , payloadEncoding] of candidates)
|
|
36
|
+
if (payloadEncodings |= payloadEncoding, payloadEncodings === 3)
|
|
40
37
|
throw new JWSInvalid("inconsistent use of JWS Unencoded Payload (RFC7797)");
|
|
41
38
|
for (const candidate of candidates)
|
|
42
39
|
try {
|
|
43
|
-
|
|
40
|
+
const [result] = await verifySignature(candidate[0], shared, key, encodeJsonUnencodedPayload, candidate[1]);
|
|
41
|
+
return result;
|
|
44
42
|
} catch {
|
|
45
43
|
}
|
|
46
44
|
throw new JWSSignatureVerificationFailed();
|
|
@@ -2,12 +2,11 @@ import { prepareDecrypt, decryptCompact } from "../lib/jwe_decrypt.js";
|
|
|
2
2
|
import { validateClaimsSet } from "../lib/jwt_claims_set.js";
|
|
3
3
|
import { JWTClaimValidationFailed } from "../util/errors.js";
|
|
4
4
|
async function jwtDecrypt(jwt, key, options) {
|
|
5
|
-
const
|
|
5
|
+
const { plaintext, ...result } = await decryptCompact(jwt, prepareDecrypt(options), key), { protectedHeader } = result, payload = validateClaimsSet(protectedHeader, plaintext, options);
|
|
6
6
|
for (const claim of ["iss", "sub", "aud"])
|
|
7
7
|
if (protectedHeader[claim] !== void 0 && (claim === "aud" ? JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud) : protectedHeader[claim] !== payload[claim]))
|
|
8
8
|
throw new JWTClaimValidationFailed(`replicated "${claim}" claim header parameter mismatch`, payload, claim, "mismatch");
|
|
9
|
-
|
|
10
|
-
return typeof key == "function" ? { ...result, key: decrypted[2] } : result;
|
|
9
|
+
return { payload, ...result };
|
|
11
10
|
}
|
|
12
11
|
export {
|
|
13
12
|
jwtDecrypt
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import { createJWE } from "../lib/jwe_encrypt.js";
|
|
2
|
-
import { JWTClaimsBuilder, jwtClaim,
|
|
3
|
-
import { assertNotSet } from "../lib/
|
|
1
|
+
import { compactJWE, createJWE } from "../lib/jwe_encrypt.js";
|
|
2
|
+
import { JWTClaimsBuilder, jwtClaim, jwtClaimsSetBytes } from "../lib/jwt_claims_set.js";
|
|
3
|
+
import { assertNotSet } from "../lib/validate.js";
|
|
4
4
|
const EncryptJWT_base = JWTClaimsBuilder;
|
|
5
5
|
class EncryptJWT extends EncryptJWT_base {
|
|
6
|
-
#
|
|
7
|
-
#iv;
|
|
8
|
-
#keyManagementParameters;
|
|
9
|
-
#protectedHeader;
|
|
6
|
+
#input = [void 0];
|
|
10
7
|
#replicateIssuerAsHeader;
|
|
11
8
|
#replicateSubjectAsHeader;
|
|
12
9
|
#replicateAudienceAsHeader;
|
|
13
10
|
setProtectedHeader(protectedHeader) {
|
|
14
|
-
return assertNotSet(this.#
|
|
11
|
+
return assertNotSet(this.#input[1], "setProtectedHeader"), this.#input[1] = protectedHeader, this;
|
|
15
12
|
}
|
|
16
13
|
setKeyManagementParameters(parameters) {
|
|
17
|
-
return assertNotSet(this.#
|
|
14
|
+
return assertNotSet(this.#input[7], "setKeyManagementParameters"), this.#input[7] = parameters, this;
|
|
18
15
|
}
|
|
19
16
|
setContentEncryptionKey(cek) {
|
|
20
|
-
return assertNotSet(this.#
|
|
17
|
+
return assertNotSet(this.#input[5], "setContentEncryptionKey"), this.#input[5] = cek, this;
|
|
21
18
|
}
|
|
22
19
|
setInitializationVector(iv) {
|
|
23
|
-
return assertNotSet(this.#
|
|
20
|
+
return assertNotSet(this.#input[6], "setInitializationVector"), this.#input[6] = iv, this;
|
|
24
21
|
}
|
|
25
22
|
replicateIssuerAsHeader() {
|
|
26
23
|
return this.#replicateIssuerAsHeader = !0, this;
|
|
@@ -32,26 +29,15 @@ class EncryptJWT extends EncryptJWT_base {
|
|
|
32
29
|
return this.#replicateAudienceAsHeader = !0, this;
|
|
33
30
|
}
|
|
34
31
|
async encrypt(key, options) {
|
|
35
|
-
const plaintext =
|
|
36
|
-
this.#
|
|
37
|
-
...this.#
|
|
32
|
+
const plaintext = jwtClaimsSetBytes(this);
|
|
33
|
+
this.#input[1] && (this.#replicateIssuerAsHeader || this.#replicateSubjectAsHeader || this.#replicateAudienceAsHeader) && (this.#input[1] = {
|
|
34
|
+
...this.#input[1],
|
|
38
35
|
iss: this.#replicateIssuerAsHeader ? jwtClaim(this, "iss") : void 0,
|
|
39
36
|
sub: this.#replicateSubjectAsHeader ? jwtClaim(this, "sub") : void 0,
|
|
40
37
|
aud: this.#replicateAudienceAsHeader ? jwtClaim(this, "aud") : void 0
|
|
41
38
|
});
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
this.#protectedHeader,
|
|
45
|
-
void 0,
|
|
46
|
-
void 0,
|
|
47
|
-
void 0,
|
|
48
|
-
this.#cek,
|
|
49
|
-
this.#iv,
|
|
50
|
-
this.#keyManagementParameters,
|
|
51
|
-
void 0,
|
|
52
|
-
!1
|
|
53
|
-
], key, options);
|
|
54
|
-
return [jwe.protected, jwe.encrypted_key, jwe.iv, jwe.ciphertext, jwe.tag].join(".");
|
|
39
|
+
const input = [...this.#input];
|
|
40
|
+
return input[0] = plaintext, compactJWE(await createJWE(input, key, options));
|
|
55
41
|
}
|
|
56
42
|
}
|
|
57
43
|
export {
|
package/dist/webapi/jwt/sign.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createCompactSignature } from "../lib/jws_sign.js";
|
|
2
2
|
import { JWTInvalid } from "../util/errors.js";
|
|
3
|
-
import { JWTClaimsBuilder,
|
|
4
|
-
import { assertNotSet } from "../lib/
|
|
3
|
+
import { JWTClaimsBuilder, jwtClaimsSetBytes } from "../lib/jwt_claims_set.js";
|
|
4
|
+
import { assertNotSet } from "../lib/validate.js";
|
|
5
5
|
const SignJWT_base = JWTClaimsBuilder;
|
|
6
6
|
class SignJWT extends SignJWT_base {
|
|
7
7
|
#protectedHeader;
|
|
@@ -9,7 +9,7 @@ class SignJWT extends SignJWT_base {
|
|
|
9
9
|
return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
|
|
10
10
|
}
|
|
11
11
|
async sign(key, options) {
|
|
12
|
-
return createCompactSignature(
|
|
12
|
+
return createCompactSignature(jwtClaimsSetBytes(this), this.#protectedHeader, options?.crit, key, () => {
|
|
13
13
|
throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
14
14
|
});
|
|
15
15
|
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import * as b64u from "../util/base64url.js";
|
|
2
|
-
import { decodeBase64url, parseJoseHeader } from "../lib/
|
|
2
|
+
import { decodeBase64url, parseJoseHeader, JWS_RECOGNIZED, validateB64, validateCrit } from "../lib/validate.js";
|
|
3
3
|
import { JWSInvalid, JWTInvalid } from "../util/errors.js";
|
|
4
|
-
import { validateClaimsSet, JWTClaimsBuilder,
|
|
5
|
-
import { JWS_RECOGNIZED, validateB64, validateCrit } from "../lib/options.js";
|
|
4
|
+
import { validateClaimsSet, JWTClaimsBuilder, jwtClaimsSetBytes } from "../lib/jwt_claims_set.js";
|
|
6
5
|
const UnsecuredJWT_base = JWTClaimsBuilder;
|
|
7
6
|
class UnsecuredJWT extends UnsecuredJWT_base {
|
|
8
7
|
encode() {
|
|
9
|
-
const
|
|
10
|
-
return `${
|
|
8
|
+
const encodedProtectedHeader = b64u.encode(JSON.stringify({ alg: "none" })), encodedPayload = b64u.encode(jwtClaimsSetBytes(this));
|
|
9
|
+
return `${encodedProtectedHeader}.${encodedPayload}.`;
|
|
11
10
|
}
|
|
12
11
|
static decode(jwt, options) {
|
|
13
12
|
if (typeof jwt != "string")
|
|
@@ -2,11 +2,11 @@ import { prepareVerify, verifyCompact } from "../lib/jws_verify.js";
|
|
|
2
2
|
import { validateClaimsSet } from "../lib/jwt_claims_set.js";
|
|
3
3
|
import { JWTInvalid } from "../util/errors.js";
|
|
4
4
|
async function jwtVerify(jwt, key, options) {
|
|
5
|
-
const verified = await verifyCompact(jwt, prepareVerify(options), key);
|
|
6
|
-
if (!
|
|
5
|
+
const [verified, b64] = await verifyCompact(jwt, prepareVerify(options), key);
|
|
6
|
+
if (!b64)
|
|
7
7
|
throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
8
|
-
const
|
|
9
|
-
return
|
|
8
|
+
const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
|
|
9
|
+
return { ...verified, payload };
|
|
10
10
|
}
|
|
11
11
|
export {
|
|
12
12
|
jwtVerify
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { toSPKI as exportPublic, toPKCS8 as exportPrivate } from "../lib/asn1.js";
|
|
2
|
-
import { invalidKeyInput } from "../lib/
|
|
2
|
+
import { invalidKeyInput, isCryptoKey, isKeyObject } from "../lib/key.js";
|
|
3
3
|
import { encode as b64u } from "../util/base64url.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
function exportSPKI(key) {
|
|
5
|
+
return exportPublic(key);
|
|
6
|
+
}
|
|
7
|
+
function exportPKCS8(key) {
|
|
8
|
+
return exportPrivate(key);
|
|
7
9
|
}
|
|
8
|
-
async function
|
|
10
|
+
async function exportJWK(key) {
|
|
9
11
|
if (isKeyObject(key))
|
|
10
12
|
if (key.type === "secret")
|
|
11
13
|
key = key.export();
|
|
@@ -20,17 +22,11 @@ async function keyToJWK(key) {
|
|
|
20
22
|
throw new TypeError(invalidKeyInput(key, "CryptoKey", "KeyObject", "Uint8Array"));
|
|
21
23
|
if (!key.extractable)
|
|
22
24
|
throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
function exportPKCS8(key) {
|
|
30
|
-
return exportPrivate(key);
|
|
31
|
-
}
|
|
32
|
-
function exportJWK(key) {
|
|
33
|
-
return keyToJWK(key);
|
|
25
|
+
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
26
|
+
delete jwk.ext, delete jwk.key_ops, delete jwk.use, jwk.kty !== "AKP" && delete jwk.alg;
|
|
27
|
+
for (const parameter of Object.keys(jwk))
|
|
28
|
+
jwk[parameter] === void 0 && delete jwk[parameter];
|
|
29
|
+
return jwk;
|
|
34
30
|
}
|
|
35
31
|
export {
|
|
36
32
|
exportJWK,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JOSENotSupported } from "../util/errors.js";
|
|
2
|
-
import { validateExtractableOption } from "../lib/
|
|
2
|
+
import { validateExtractableOption } from "../lib/key.js";
|
|
3
3
|
import { keyAlgorithm, unsupportedAlg, algArgument } from "../lib/key_algorithm.js";
|
|
4
4
|
function getModulusLengthOption(options) {
|
|
5
5
|
const modulusLength = options?.modulusLength ?? 2048;
|
|
@@ -13,18 +13,9 @@ async function generateKeyPair(alg, options) {
|
|
|
13
13
|
let algorithm;
|
|
14
14
|
if (entry.resolve) {
|
|
15
15
|
const crv = options?.crv ?? "P-256";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
case "P-521":
|
|
20
|
-
algorithm = { name: "ECDH", namedCurve: crv };
|
|
21
|
-
break;
|
|
22
|
-
case "X25519":
|
|
23
|
-
algorithm = { name: "X25519" };
|
|
24
|
-
break;
|
|
25
|
-
default:
|
|
26
|
-
throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, and X25519");
|
|
27
|
-
}
|
|
16
|
+
if (!["P-256", "P-384", "P-521", "X25519"].includes(crv))
|
|
17
|
+
throw new JOSENotSupported("Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, and X25519");
|
|
18
|
+
algorithm = entry.resolve({ crv });
|
|
28
19
|
} else {
|
|
29
20
|
if (entry.crv !== void 0 && options?.crv !== void 0 && options.crv !== entry.crv)
|
|
30
21
|
throw new JOSENotSupported(`Invalid or unsupported crv option provided, the only supported value for ${alg} is ${entry.crv}`);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { unsupportedAlg, algArgument } from "../lib/key_algorithm.js";
|
|
2
|
-
import { validateExtractableOption } from "../lib/
|
|
2
|
+
import { validateExtractableOption } from "../lib/key.js";
|
|
3
3
|
async function generateSecret(alg, options) {
|
|
4
4
|
const extractable = validateExtractableOption(options?.extractable);
|
|
5
|
-
let
|
|
5
|
+
let keyLengthBits, algorithm, keyUsages;
|
|
6
6
|
switch (alg) {
|
|
7
7
|
case "HS256":
|
|
8
8
|
case "HS384":
|
|
9
9
|
case "HS512":
|
|
10
|
-
|
|
10
|
+
keyLengthBits = +alg.slice(-3), algorithm = { name: "HMAC", hash: `SHA-${keyLengthBits}`, length: keyLengthBits }, keyUsages = ["sign", "verify"];
|
|
11
11
|
break;
|
|
12
12
|
case "A128CBC-HS256":
|
|
13
13
|
case "A192CBC-HS384":
|
|
@@ -16,7 +16,7 @@ async function generateSecret(alg, options) {
|
|
|
16
16
|
case "A128KW":
|
|
17
17
|
case "A192KW":
|
|
18
18
|
case "A256KW":
|
|
19
|
-
|
|
19
|
+
keyLengthBits = +alg.slice(1, 4), algorithm = { name: "AES-KW", length: keyLengthBits }, keyUsages = ["wrapKey", "unwrapKey"];
|
|
20
20
|
break;
|
|
21
21
|
case "A128GCMKW":
|
|
22
22
|
case "A192GCMKW":
|
|
@@ -24,7 +24,7 @@ async function generateSecret(alg, options) {
|
|
|
24
24
|
case "A128GCM":
|
|
25
25
|
case "A192GCM":
|
|
26
26
|
case "A256GCM":
|
|
27
|
-
|
|
27
|
+
keyLengthBits = +alg.slice(1, 4), algorithm = { name: "AES-GCM", length: keyLengthBits }, keyUsages = ["encrypt", "decrypt"];
|
|
28
28
|
break;
|
|
29
29
|
default:
|
|
30
30
|
unsupportedAlg(algArgument);
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { decode as decodeBase64URL } from "../util/base64url.js";
|
|
2
2
|
import { fromSPKI, fromPKCS8, fromX509 } from "../lib/asn1.js";
|
|
3
|
-
import { jwkToKey } from "../lib/
|
|
3
|
+
import { jwkToKey, validateExtractableOption, normalizeJwk } from "../lib/key.js";
|
|
4
4
|
import { keyAlgorithm } from "../lib/key_algorithm.js";
|
|
5
5
|
import { JOSENotSupported } from "../util/errors.js";
|
|
6
|
-
import { isObject } from "../lib/
|
|
7
|
-
import { validateExtractableOption } from "../lib/key_options.js";
|
|
8
|
-
import { normalizeJwk } from "../lib/jwk_metadata.js";
|
|
6
|
+
import { isObject } from "../lib/validate.js";
|
|
9
7
|
async function importSPKI(spki, alg, options) {
|
|
10
8
|
if (typeof spki != "string" || spki.indexOf("-----BEGIN PUBLIC KEY-----") !== 0)
|
|
11
9
|
throw new TypeError('"spki" must be SPKI formatted string');
|
|
@@ -25,9 +23,7 @@ async function importJWK(jwk, alg, options) {
|
|
|
25
23
|
if (!isObject(jwk))
|
|
26
24
|
throw new TypeError("JWK must be an object");
|
|
27
25
|
const normalized = normalizeJwk(jwk), extractable = validateExtractableOption(options?.extractable), { alg: jwkAlg } = normalized;
|
|
28
|
-
alg ??= jwkAlg
|
|
29
|
-
const ext = extractable ?? normalized.ext;
|
|
30
|
-
if (normalized.kty !== "oct" && !alg)
|
|
26
|
+
if (alg ??= jwkAlg, normalized.kty !== "oct" && !alg)
|
|
31
27
|
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
|
|
32
28
|
switch (normalized.kty) {
|
|
33
29
|
case "oct":
|
|
@@ -39,12 +35,12 @@ async function importJWK(jwk, alg, options) {
|
|
|
39
35
|
throw new TypeError('missing "alg" (Algorithm) Parameter value');
|
|
40
36
|
if (alg !== jwkAlg)
|
|
41
37
|
throw new TypeError("JWK alg and alg option value mismatch");
|
|
42
|
-
return jwkToKey(keyAlgorithm(alg),
|
|
38
|
+
return jwkToKey(keyAlgorithm(alg), normalized, extractable);
|
|
43
39
|
}
|
|
44
40
|
case "RSA":
|
|
45
41
|
case "EC":
|
|
46
42
|
case "OKP":
|
|
47
|
-
return jwkToKey(keyAlgorithm(alg),
|
|
43
|
+
return jwkToKey(keyAlgorithm(alg), normalized, extractable);
|
|
48
44
|
default:
|
|
49
45
|
throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
|
|
50
46
|
}
|
package/dist/webapi/lib/asn1.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { invalidKeyInput } from "./
|
|
2
|
-
import { encodeBase64, decodeBase64 } from "
|
|
1
|
+
import { invalidKeyInput, isCryptoKey, isKeyObject, validateExtractableOption } from "./key.js";
|
|
2
|
+
import { encodeBase64, decodeBase64 } from "./buffer_utils.js";
|
|
3
3
|
import { JOSENotSupported } from "../util/errors.js";
|
|
4
4
|
import { keyAlgorithm, unsupportedAlg, algArgument } from "./key_algorithm.js";
|
|
5
|
-
import { isCryptoKey, isKeyObject } from "./is_key_like.js";
|
|
6
|
-
import { validateExtractableOption } from "./key_options.js";
|
|
7
5
|
const formatPEM = (b64, descriptor) => {
|
|
8
6
|
const newlined = (b64.match(/.{1,64}/g) || []).join(`
|
|
9
7
|
`);
|
|
@@ -96,8 +94,8 @@ const parseECAlgorithmIdentifier = (state) => {
|
|
|
96
94
|
try {
|
|
97
95
|
const state = createASN1State(keyData);
|
|
98
96
|
parseKeyHeader(state, keyFormat), algorithm = entry.resolve({ crv: parseECAlgorithmIdentifier(state) });
|
|
99
|
-
} catch {
|
|
100
|
-
throw new JOSENotSupported("Invalid or unsupported key format");
|
|
97
|
+
} catch (cause) {
|
|
98
|
+
throw new JOSENotSupported("Invalid or unsupported key format", { cause });
|
|
101
99
|
}
|
|
102
100
|
else
|
|
103
101
|
algorithm = entry.subtle;
|