jose 6.2.9 → 6.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/jwe/compact/decrypt.d.ts +7 -16
- package/dist/types/jwe/compact/encrypt.d.ts +6 -17
- package/dist/types/jwe/flattened/decrypt.d.ts +7 -16
- package/dist/types/jwe/flattened/encrypt.d.ts +11 -34
- package/dist/types/jwe/general/decrypt.d.ts +7 -16
- package/dist/types/jwe/general/encrypt.d.ts +15 -35
- package/dist/types/jwk/embedded.d.ts +3 -8
- package/dist/types/jwk/thumbprint.d.ts +5 -5
- package/dist/types/jwks/local.d.ts +6 -10
- package/dist/types/jwks/remote.d.ts +17 -28
- package/dist/types/jws/compact/sign.d.ts +5 -10
- package/dist/types/jws/compact/verify.d.ts +9 -18
- package/dist/types/jws/flattened/sign.d.ts +7 -16
- package/dist/types/jws/flattened/verify.d.ts +9 -18
- package/dist/types/jws/general/sign.d.ts +11 -21
- package/dist/types/jws/general/verify.d.ts +12 -21
- package/dist/types/jwt/decrypt.d.ts +10 -20
- package/dist/types/jwt/encrypt.d.ts +13 -26
- package/dist/types/jwt/sign.d.ts +12 -19
- package/dist/types/jwt/unsecured.d.ts +17 -28
- package/dist/types/jwt/verify.d.ts +9 -19
- package/dist/types/key/export.d.ts +4 -4
- package/dist/types/key/generate_key_pair.d.ts +6 -8
- package/dist/types/key/generate_secret.d.ts +4 -11
- package/dist/types/key/import.d.ts +10 -17
- package/dist/types/types.d.ts +44 -84
- package/dist/types/util/base64url.d.ts +2 -2
- package/dist/types/util/decode_jwt.d.ts +3 -10
- package/dist/types/util/decode_protected_header.d.ts +4 -4
- package/dist/types/util/errors.d.ts +26 -53
- package/dist/webapi/index.js +70 -32
- package/dist/webapi/jwe/compact/decrypt.js +7 -8
- package/dist/webapi/jwe/compact/encrypt.js +42 -26
- package/dist/webapi/jwe/flattened/decrypt.js +14 -10
- package/dist/webapi/jwe/flattened/encrypt.js +53 -71
- package/dist/webapi/jwe/general/decrypt.js +38 -49
- package/dist/webapi/jwe/general/encrypt.js +121 -162
- package/dist/webapi/jwk/embedded.js +30 -18
- package/dist/webapi/jwk/thumbprint.js +54 -64
- package/dist/webapi/jwks/local.js +49 -74
- package/dist/webapi/jwks/remote.js +91 -160
- package/dist/webapi/jws/compact/sign.js +21 -20
- package/dist/webapi/jws/compact/verify.js +7 -8
- package/dist/webapi/jws/flattened/sign.js +29 -30
- package/dist/webapi/jws/flattened/verify.js +21 -23
- package/dist/webapi/jws/general/sign.js +61 -70
- package/dist/webapi/jws/general/verify.js +47 -41
- package/dist/webapi/jwt/decrypt.js +13 -22
- package/dist/webapi/jwt/encrypt.js +58 -100
- package/dist/webapi/jwt/sign.js +18 -50
- package/dist/webapi/jwt/unsecured.js +34 -63
- package/dist/webapi/jwt/verify.js +12 -14
- package/dist/webapi/key/export.js +32 -37
- package/dist/webapi/key/generate_key_pair.js +40 -44
- package/dist/webapi/key/generate_secret.js +35 -39
- package/dist/webapi/key/import.js +52 -52
- package/dist/webapi/lib/asn1.js +130 -164
- package/dist/webapi/lib/base64.js +18 -20
- package/dist/webapi/lib/buffer_utils.js +34 -38
- package/dist/webapi/lib/content_encryption.js +79 -123
- package/dist/webapi/lib/crypto_key.js +24 -25
- package/dist/webapi/lib/deflate.js +46 -40
- package/dist/webapi/lib/helpers.js +40 -37
- package/dist/webapi/lib/invalid_key_input.js +10 -24
- package/dist/webapi/lib/is_key_like.js +17 -15
- package/dist/webapi/lib/jwe_algorithms.js +106 -93
- package/dist/webapi/lib/jwe_decrypt.js +210 -176
- package/dist/webapi/lib/jwe_encrypt.js +104 -110
- package/dist/webapi/lib/jwk_metadata.js +19 -0
- package/dist/webapi/lib/jwk_to_key.js +9 -16
- package/dist/webapi/lib/jws_algorithms.js +62 -61
- package/dist/webapi/lib/jws_sign.js +58 -72
- package/dist/webapi/lib/jws_verify.js +90 -103
- package/dist/webapi/lib/jwt_claims_set.js +134 -185
- package/dist/webapi/lib/key.js +84 -121
- package/dist/webapi/lib/key_algorithm.js +13 -8
- package/dist/webapi/lib/key_descriptor.js +8 -6
- package/dist/webapi/lib/key_management.js +200 -225
- package/dist/webapi/lib/key_options.js +8 -0
- package/dist/webapi/lib/options.js +57 -44
- package/dist/webapi/lib/signing.js +18 -22
- package/dist/webapi/lib/type_checks.js +28 -33
- package/dist/webapi/util/base64url.js +26 -35
- package/dist/webapi/util/decode_jwt.js +32 -31
- package/dist/webapi/util/decode_protected_header.js +18 -23
- package/dist/webapi/util/errors.js +94 -84
- package/package.json +17 -81
|
@@ -1,170 +1,101 @@
|
|
|
1
|
-
import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from
|
|
2
|
-
import { createLocalJWKSet } from
|
|
3
|
-
import {
|
|
1
|
+
import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from "../util/errors.js";
|
|
2
|
+
import { createLocalJWKSet } from "./local.js";
|
|
3
|
+
import { isJwkSet } from "../lib/type_checks.js";
|
|
4
4
|
function isCloudflareWorkers() {
|
|
5
|
-
|
|
6
|
-
(typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||
|
|
7
|
-
(typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel'));
|
|
5
|
+
return typeof WebSocketPair < "u" || typeof navigator < "u" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime < "u" && EdgeRuntime === "vercel";
|
|
8
6
|
}
|
|
9
7
|
let USER_AGENT;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const VERSION = 'v6.2.9';
|
|
13
|
-
USER_AGENT = `${NAME}/${VERSION}`;
|
|
14
|
-
}
|
|
15
|
-
export const customFetch = Symbol();
|
|
8
|
+
(typeof navigator > "u" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) && (USER_AGENT = "jose/v6.2.11");
|
|
9
|
+
const customFetch = /* @__PURE__ */ Symbol();
|
|
16
10
|
async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return await response.json();
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON');
|
|
36
|
-
}
|
|
11
|
+
const response = await fetchImpl(url, {
|
|
12
|
+
method: "GET",
|
|
13
|
+
signal,
|
|
14
|
+
redirect: "manual",
|
|
15
|
+
headers
|
|
16
|
+
}).catch((err) => {
|
|
17
|
+
throw err.name === "TimeoutError" ? new JWKSTimeout() : err;
|
|
18
|
+
});
|
|
19
|
+
if (response.status !== 200)
|
|
20
|
+
throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response");
|
|
21
|
+
try {
|
|
22
|
+
return await response.json();
|
|
23
|
+
} catch {
|
|
24
|
+
throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON");
|
|
25
|
+
}
|
|
37
26
|
}
|
|
38
|
-
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
if (!('uat' in input) || typeof input.uat !== 'number' || Date.now() - input.uat >= cacheMaxAge) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
if (!('jwks' in input) ||
|
|
47
|
-
!isObject(input.jwks) ||
|
|
48
|
-
!Array.isArray(input.jwks.keys) ||
|
|
49
|
-
!Array.prototype.every.call(input.jwks.keys, isObject)) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
return true;
|
|
27
|
+
const jwksCache = /* @__PURE__ */ Symbol();
|
|
28
|
+
function isFreshFor(timestamp, duration) {
|
|
29
|
+
return Number.isFinite(timestamp) && Date.now() < timestamp + duration;
|
|
53
30
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (cache !== undefined) {
|
|
86
|
-
this.#cache = cache;
|
|
87
|
-
if (isFreshJwksCache(cache, this.#cacheMaxAge)) {
|
|
88
|
-
this.#jwksTimestamp = this.#cache.uat;
|
|
89
|
-
this.#local = createLocalJWKSet(this.#cache.jwks);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
pendingFetch() {
|
|
94
|
-
return !!this.#pendingFetch;
|
|
95
|
-
}
|
|
96
|
-
#validFor(duration) {
|
|
97
|
-
return typeof this.#jwksTimestamp === 'number' && Date.now() < this.#jwksTimestamp + duration;
|
|
98
|
-
}
|
|
99
|
-
coolingDown() {
|
|
100
|
-
return this.#validFor(this.#cooldownDuration);
|
|
101
|
-
}
|
|
102
|
-
fresh() {
|
|
103
|
-
return this.#validFor(this.#cacheMaxAge);
|
|
104
|
-
}
|
|
105
|
-
jwks() {
|
|
106
|
-
return this.#local?.jwks();
|
|
31
|
+
function validateDuration(value, fallback, option) {
|
|
32
|
+
if (Number.isNaN(value))
|
|
33
|
+
throw new TypeError(`"${option}" option must not be NaN`);
|
|
34
|
+
return typeof value == "number" ? value : fallback;
|
|
35
|
+
}
|
|
36
|
+
function createRemoteJWKSet(url, options) {
|
|
37
|
+
if (!(url instanceof URL))
|
|
38
|
+
throw new TypeError("url must be an instance of URL");
|
|
39
|
+
const href = new URL(url.href).href, opts = options ?? {}, timeoutOption = opts.timeoutDuration;
|
|
40
|
+
if (typeof timeoutOption == "number" && (!Number.isInteger(timeoutOption) || timeoutOption < 0))
|
|
41
|
+
throw new TypeError('"timeoutDuration" option must be a non-negative integer');
|
|
42
|
+
const timeoutDuration = typeof timeoutOption == "number" ? timeoutOption : 5e3, cooldownDuration = validateDuration(opts.cooldownDuration, 3e4, "cooldownDuration"), cacheMaxAge = validateDuration(opts.cacheMaxAge, 6e5, "cacheMaxAge"), headers = new Headers(opts.headers);
|
|
43
|
+
USER_AGENT && !headers.has("User-Agent") && headers.set("User-Agent", USER_AGENT), headers.has("accept") || headers.set("accept", "application/json, application/jwk-set+json");
|
|
44
|
+
const fetchImpl = opts[customFetch], cache = opts[jwksCache];
|
|
45
|
+
let jwksTimestamp, pendingFetch, reloadSequence = 0, appliedSequence = 0, local;
|
|
46
|
+
if (cache && typeof cache == "object") {
|
|
47
|
+
const { uat, jwks } = cache;
|
|
48
|
+
isFreshFor(uat, cacheMaxAge) && isJwkSet(jwks) && (jwksTimestamp = uat, local = createLocalJWKSet(jwks));
|
|
49
|
+
}
|
|
50
|
+
const reload = async () => {
|
|
51
|
+
if (pendingFetch && isCloudflareWorkers() && (pendingFetch = void 0), !pendingFetch) {
|
|
52
|
+
const sequence = ++reloadSequence, current = pendingFetch = fetchJwks(href, headers, AbortSignal.timeout(timeoutDuration), fetchImpl).then((json) => {
|
|
53
|
+
const next = createLocalJWKSet(json);
|
|
54
|
+
if (sequence <= appliedSequence)
|
|
55
|
+
return;
|
|
56
|
+
local = next;
|
|
57
|
+
const updatedAt = Date.now();
|
|
58
|
+
cache && (cache.uat = updatedAt, cache.jwks = json), jwksTimestamp = updatedAt, appliedSequence = sequence;
|
|
59
|
+
}).finally(() => {
|
|
60
|
+
pendingFetch === current && (pendingFetch = void 0);
|
|
61
|
+
});
|
|
107
62
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
await this.reload();
|
|
119
|
-
return this.#local(protectedHeader, token);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
throw err;
|
|
123
|
-
}
|
|
63
|
+
await pendingFetch;
|
|
64
|
+
};
|
|
65
|
+
return Object.defineProperties(async (protectedHeader, token) => {
|
|
66
|
+
(!local || !isFreshFor(jwksTimestamp, cacheMaxAge)) && await reload();
|
|
67
|
+
try {
|
|
68
|
+
return await local(protectedHeader, token);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
if (err instanceof JWKSNoMatchingKey && !isFreshFor(jwksTimestamp, cooldownDuration))
|
|
71
|
+
return await reload(), local(protectedHeader, token);
|
|
72
|
+
throw err;
|
|
124
73
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
74
|
+
}, {
|
|
75
|
+
coolingDown: {
|
|
76
|
+
get: () => isFreshFor(jwksTimestamp, cooldownDuration),
|
|
77
|
+
enumerable: !0
|
|
78
|
+
},
|
|
79
|
+
fresh: {
|
|
80
|
+
get: () => isFreshFor(jwksTimestamp, cacheMaxAge),
|
|
81
|
+
enumerable: !0
|
|
82
|
+
},
|
|
83
|
+
reload: {
|
|
84
|
+
value: reload,
|
|
85
|
+
enumerable: !0
|
|
86
|
+
},
|
|
87
|
+
reloading: {
|
|
88
|
+
get: () => !!pendingFetch,
|
|
89
|
+
enumerable: !0
|
|
90
|
+
},
|
|
91
|
+
jwks: {
|
|
92
|
+
value: () => local?.jwks(),
|
|
93
|
+
enumerable: !0
|
|
142
94
|
}
|
|
95
|
+
});
|
|
143
96
|
}
|
|
144
|
-
export
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
get: () => set.coolingDown(),
|
|
150
|
-
enumerable: true,
|
|
151
|
-
},
|
|
152
|
-
fresh: {
|
|
153
|
-
get: () => set.fresh(),
|
|
154
|
-
enumerable: true,
|
|
155
|
-
},
|
|
156
|
-
reload: {
|
|
157
|
-
value: () => set.reload(),
|
|
158
|
-
enumerable: true,
|
|
159
|
-
},
|
|
160
|
-
reloading: {
|
|
161
|
-
get: () => set.pendingFetch(),
|
|
162
|
-
enumerable: true,
|
|
163
|
-
},
|
|
164
|
-
jwks: {
|
|
165
|
-
value: () => set.jwks(),
|
|
166
|
-
enumerable: true,
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
return remoteJWKSet;
|
|
170
|
-
}
|
|
97
|
+
export {
|
|
98
|
+
createRemoteJWKSet,
|
|
99
|
+
customFetch,
|
|
100
|
+
jwksCache
|
|
101
|
+
};
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return `${jws.protected}.${jws.payload}.${jws.signature}`;
|
|
20
|
-
}
|
|
1
|
+
import { createCompactSignature } from "../../lib/jws_sign.js";
|
|
2
|
+
import { assertNotSet } from "../../lib/helpers.js";
|
|
3
|
+
class CompactSign {
|
|
4
|
+
#payload;
|
|
5
|
+
#protectedHeader;
|
|
6
|
+
constructor(payload) {
|
|
7
|
+
if (!(payload instanceof Uint8Array))
|
|
8
|
+
throw new TypeError("payload must be an instance of Uint8Array");
|
|
9
|
+
this.#payload = payload;
|
|
10
|
+
}
|
|
11
|
+
setProtectedHeader(protectedHeader) {
|
|
12
|
+
return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
|
|
13
|
+
}
|
|
14
|
+
async sign(key, options) {
|
|
15
|
+
return createCompactSignature(this.#payload, this.#protectedHeader, options?.crit, key, () => {
|
|
16
|
+
throw new TypeError("use the flattened module for creating JWS with b64: false");
|
|
17
|
+
});
|
|
18
|
+
}
|
|
21
19
|
}
|
|
20
|
+
export {
|
|
21
|
+
CompactSign
|
|
22
|
+
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { prepareVerify, verifyCompact } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (typeof key === 'function') {
|
|
6
|
-
return { ...result, key: verified[3] };
|
|
7
|
-
}
|
|
8
|
-
return result;
|
|
1
|
+
import { prepareVerify, verifyCompact } from "../../lib/jws_verify.js";
|
|
2
|
+
async function compactVerify(jws, key, options) {
|
|
3
|
+
const verified = await verifyCompact(jws, prepareVerify(options), key), result = { payload: verified[0], protectedHeader: verified[1] };
|
|
4
|
+
return typeof key == "function" ? { ...result, key: verified[3] } : result;
|
|
9
5
|
}
|
|
6
|
+
export {
|
|
7
|
+
compactVerify
|
|
8
|
+
};
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
import { createSignature } from
|
|
2
|
-
import { assertNotSet } from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
unprotectedHeader: this.#unprotectedHeader,
|
|
28
|
-
crit: options?.crit,
|
|
29
|
-
}, key);
|
|
30
|
-
}
|
|
1
|
+
import { createSignature } from "../../lib/jws_sign.js";
|
|
2
|
+
import { assertNotSet } from "../../lib/helpers.js";
|
|
3
|
+
class FlattenedSign {
|
|
4
|
+
#payload;
|
|
5
|
+
#protectedHeader;
|
|
6
|
+
#unprotectedHeader;
|
|
7
|
+
constructor(payload) {
|
|
8
|
+
if (!(payload instanceof Uint8Array))
|
|
9
|
+
throw new TypeError("payload must be an instance of Uint8Array");
|
|
10
|
+
this.#payload = payload;
|
|
11
|
+
}
|
|
12
|
+
setProtectedHeader(protectedHeader) {
|
|
13
|
+
return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
|
|
14
|
+
}
|
|
15
|
+
setUnprotectedHeader(unprotectedHeader) {
|
|
16
|
+
return assertNotSet(this.#unprotectedHeader, "setUnprotectedHeader"), this.#unprotectedHeader = unprotectedHeader, this;
|
|
17
|
+
}
|
|
18
|
+
async sign(key, options) {
|
|
19
|
+
const [jws] = await createSignature({
|
|
20
|
+
payload: this.#payload,
|
|
21
|
+
protectedHeader: this.#protectedHeader,
|
|
22
|
+
unprotectedHeader: this.#unprotectedHeader,
|
|
23
|
+
crit: options?.crit
|
|
24
|
+
}, key);
|
|
25
|
+
return jws;
|
|
26
|
+
}
|
|
31
27
|
}
|
|
28
|
+
export {
|
|
29
|
+
FlattenedSign
|
|
30
|
+
};
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
import { JWSInvalid } from
|
|
2
|
-
import { isObject } from
|
|
3
|
-
import { prepareVerify, verifySignature, verifyResult } from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
if (jws.header !== undefined && !isObject(jws.header)) {
|
|
21
|
-
throw new JWSInvalid('JWS Unprotected Header incorrect type');
|
|
22
|
-
}
|
|
23
|
-
return verifyResult(jws, await verifySignature(jws, prepareVerify(options), key));
|
|
1
|
+
import { JWSInvalid } from "../../util/errors.js";
|
|
2
|
+
import { isObject } from "../../lib/type_checks.js";
|
|
3
|
+
import { encodeJsonUnencodedPayload, prepareVerify, snapshotJws, verifySignature, verifyResult } from "../../lib/jws_verify.js";
|
|
4
|
+
async function flattenedVerify(jws, key, options) {
|
|
5
|
+
if (!isObject(jws))
|
|
6
|
+
throw new JWSInvalid("Flattened JWS must be an object");
|
|
7
|
+
const snapshot = snapshotJws(jws);
|
|
8
|
+
if (snapshot.protected === void 0 && snapshot.header === void 0)
|
|
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));
|
|
24
19
|
}
|
|
20
|
+
export {
|
|
21
|
+
flattenedVerify
|
|
22
|
+
};
|
|
@@ -1,74 +1,65 @@
|
|
|
1
|
-
import { createSignature } from
|
|
2
|
-
import { JWSInvalid } from
|
|
3
|
-
import { assertNotSet } from
|
|
1
|
+
import { createSignature } from "../../lib/jws_sign.js";
|
|
2
|
+
import { JWSInvalid } from "../../util/errors.js";
|
|
3
|
+
import { assertNotSet } from "../../lib/helpers.js";
|
|
4
4
|
class IndividualSignature {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
setProtectedHeader
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return this.#parent.sign(...args);
|
|
26
|
-
}
|
|
27
|
-
done() {
|
|
28
|
-
return this.#parent;
|
|
29
|
-
}
|
|
5
|
+
#parent;
|
|
6
|
+
state;
|
|
7
|
+
constructor(sig, key, options) {
|
|
8
|
+
this.#parent = sig, this.state = [void 0, void 0, key, options?.crit];
|
|
9
|
+
}
|
|
10
|
+
setProtectedHeader(protectedHeader) {
|
|
11
|
+
return assertNotSet(this.state[0], "setProtectedHeader"), this.state[0] = protectedHeader, this;
|
|
12
|
+
}
|
|
13
|
+
setUnprotectedHeader(unprotectedHeader) {
|
|
14
|
+
return assertNotSet(this.state[1], "setUnprotectedHeader"), this.state[1] = unprotectedHeader, this;
|
|
15
|
+
}
|
|
16
|
+
addSignature(...args) {
|
|
17
|
+
return this.#parent.addSignature(...args);
|
|
18
|
+
}
|
|
19
|
+
sign(...args) {
|
|
20
|
+
return this.#parent.sign(...args);
|
|
21
|
+
}
|
|
22
|
+
done() {
|
|
23
|
+
return this.#parent;
|
|
24
|
+
}
|
|
30
25
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (i === 0) {
|
|
65
|
-
jws.payload = payload;
|
|
66
|
-
}
|
|
67
|
-
else if (jws.payload !== payload) {
|
|
68
|
-
throw new JWSInvalid('inconsistent use of JWS Unencoded Payload (RFC7797)');
|
|
69
|
-
}
|
|
70
|
-
jws.signatures.push(rest);
|
|
71
|
-
}
|
|
72
|
-
return jws;
|
|
26
|
+
class GeneralSign {
|
|
27
|
+
#payload;
|
|
28
|
+
#signatures = [];
|
|
29
|
+
constructor(payload) {
|
|
30
|
+
this.#payload = payload;
|
|
31
|
+
}
|
|
32
|
+
addSignature(key, options) {
|
|
33
|
+
const signature = new IndividualSignature(this, key, options);
|
|
34
|
+
return this.#signatures.push(signature), signature;
|
|
35
|
+
}
|
|
36
|
+
async sign() {
|
|
37
|
+
if (!this.#signatures.length)
|
|
38
|
+
throw new JWSInvalid("at least one signature must be added");
|
|
39
|
+
if (!(this.#payload instanceof Uint8Array))
|
|
40
|
+
throw new TypeError("payload must be an instance of Uint8Array");
|
|
41
|
+
const jws = {
|
|
42
|
+
signatures: [],
|
|
43
|
+
payload: ""
|
|
44
|
+
}, encoded = [];
|
|
45
|
+
let b64;
|
|
46
|
+
for (let i = 0; i < this.#signatures.length; i++) {
|
|
47
|
+
const signature = this.#signatures[i], [protectedHeader, unprotectedHeader, key, crit] = signature.state, [{ payload, ...rest }, signatureB64] = await createSignature({
|
|
48
|
+
payload: this.#payload,
|
|
49
|
+
protectedHeader,
|
|
50
|
+
unprotectedHeader,
|
|
51
|
+
crit,
|
|
52
|
+
encoded
|
|
53
|
+
}, key);
|
|
54
|
+
if (b64 === void 0)
|
|
55
|
+
b64 = signatureB64, jws.payload = payload;
|
|
56
|
+
else if (b64 !== signatureB64)
|
|
57
|
+
throw new JWSInvalid("inconsistent use of JWS Unencoded Payload (RFC7797)");
|
|
58
|
+
jws.signatures.push(rest);
|
|
73
59
|
}
|
|
60
|
+
return jws;
|
|
61
|
+
}
|
|
74
62
|
}
|
|
63
|
+
export {
|
|
64
|
+
GeneralSign
|
|
65
|
+
};
|