unjwt 0.5.9 → 0.5.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/README.md +3 -3
- package/dist/index.d.mts +5 -6
- package/dist/index.mjs +5 -5
- package/dist/jwe.d.mts +2 -3
- package/dist/jwe.mjs +4 -4
- package/dist/jwk.d.mts +2 -3
- package/dist/jwk.mjs +2 -2
- package/dist/jws.d.mts +2 -3
- package/dist/jws.mjs +4 -4
- package/dist/shared/{unjwt.8w7jp2aw.d.mts → unjwt.BvhKNVNR.d.mts} +28 -30
- package/dist/shared/{unjwt.D9da8HQF.d.mts → unjwt.CN1C8TlR.d.mts} +90 -15
- package/dist/shared/{unjwt.Ca03jPX3.mjs → unjwt.C_D0RMCp.mjs} +1 -1
- package/dist/shared/unjwt.Ce8yMcp_.mjs +298 -0
- package/dist/shared/{unjwt.DH1p_WL8.d.mts → unjwt.Cz90HQhy.d.mts} +11 -12
- package/dist/shared/{unjwt.B2olxeGL.mjs → unjwt.DVMpKj8x.mjs} +22 -86
- package/dist/shared/unjwt.D_JFPtpW.mjs +161 -0
- package/dist/shared/{unjwt.DRUXIabl.mjs → unjwt.DuBBF25X.mjs} +19 -8
- package/dist/shared/{unjwt.D_Mabhgz.d.mts → unjwt.QRureeXk.d.mts} +14 -70
- package/dist/shared/unjwt.df8yQ5_5.d.mts +128 -0
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +1 -1
- package/package.json +12 -11
- package/dist/shared/unjwt.BHpknTpg.mjs +0 -93
- package/dist/shared/unjwt.BvIkEGGz.d.mts +0 -52
- package/dist/shared/unjwt.CbvzYE-m.d.mts +0 -58
- package/dist/shared/unjwt.wHjOCapq.mjs +0 -279
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
function applyTypCtyDefaults(header, payload) {
|
|
2
|
+
const isObjectPayload = typeof payload === "object" && payload !== null && !(payload instanceof Uint8Array);
|
|
3
|
+
if (header.typ === void 0 && isObjectPayload) {
|
|
4
|
+
header.typ = "at+jwt";
|
|
5
|
+
}
|
|
6
|
+
if ((header.typ === "at+jwt" || header.typ === "JWT") && isObjectPayload) {
|
|
7
|
+
header.cty ||= "application/json";
|
|
8
|
+
}
|
|
9
|
+
return header;
|
|
10
|
+
}
|
|
11
|
+
function isJsonContent(header) {
|
|
12
|
+
if (!header) return false;
|
|
13
|
+
if (header.typ === "at+jwt") return true;
|
|
14
|
+
if (header.typ === "JWT") return true;
|
|
15
|
+
const cty = header.cty?.toLowerCase();
|
|
16
|
+
return cty === "json" || cty === "application/json" || !!cty && cty.endsWith("+json");
|
|
17
|
+
}
|
|
18
|
+
function decodeMaybeJsonString(decodedString, header) {
|
|
19
|
+
if (isJsonContent(header)) {
|
|
20
|
+
const looksLikeJson = decodedString.startsWith("{") && decodedString.endsWith("}") || decodedString.startsWith("[") && decodedString.endsWith("]");
|
|
21
|
+
if (looksLikeJson) {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(decodedString);
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return decodedString;
|
|
29
|
+
}
|
|
30
|
+
function decodePayloadFromBytes(bytes, header, forceUint8Array) {
|
|
31
|
+
if (forceUint8Array) return bytes;
|
|
32
|
+
const decodedString = textDecoder.decode(bytes);
|
|
33
|
+
return decodeMaybeJsonString(decodedString, header);
|
|
34
|
+
}
|
|
35
|
+
function decodePayloadFromB64UrlSegment(payloadEncoded, header, forceUint8Array) {
|
|
36
|
+
if (forceUint8Array) return base64UrlDecode(payloadEncoded, false);
|
|
37
|
+
const decodedString = base64UrlDecode(payloadEncoded);
|
|
38
|
+
return decodeMaybeJsonString(decodedString, header);
|
|
39
|
+
}
|
|
40
|
+
function getPlaintextBytes(payload) {
|
|
41
|
+
if (payload instanceof Uint8Array) return payload;
|
|
42
|
+
if (typeof payload === "string") return textEncoder.encode(payload);
|
|
43
|
+
if (typeof payload === "object" && payload !== null)
|
|
44
|
+
return textEncoder.encode(JSON.stringify(payload));
|
|
45
|
+
throw new TypeError(
|
|
46
|
+
"Plaintext must be a string, Uint8Array, or a JSON-serializable object."
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function computeJwtTimeClaims(payload, headerTyp, expiresIn, currentDate = /* @__PURE__ */ new Date()) {
|
|
50
|
+
if (expiresIn === void 0 || headerTyp !== "at+jwt" && headerTyp !== "JWT" || !(payload && typeof payload === "object") || payload instanceof Uint8Array || payload.exp) {
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
const now = Math.round(currentDate.getTime() / 1e3);
|
|
54
|
+
const claims = { ...payload };
|
|
55
|
+
claims.iat ||= now;
|
|
56
|
+
claims.exp = now + expiresIn;
|
|
57
|
+
return claims;
|
|
58
|
+
}
|
|
59
|
+
function validateJwtClaims(jwtClaims, options = {}) {
|
|
60
|
+
const clockTolerance = options.clockTolerance ?? 0;
|
|
61
|
+
const currentTime = Math.round(
|
|
62
|
+
(options.currentDate ?? /* @__PURE__ */ new Date()).getTime() / 1e3
|
|
63
|
+
);
|
|
64
|
+
const allRequiredClaims = new Set(options.requiredClaims || []);
|
|
65
|
+
const missingClaims = /* @__PURE__ */ new Set();
|
|
66
|
+
if (options.issuer) allRequiredClaims.add("iss");
|
|
67
|
+
if (options.audience) allRequiredClaims.add("aud");
|
|
68
|
+
if (options.subject) allRequiredClaims.add("sub");
|
|
69
|
+
if (options.maxTokenAge) allRequiredClaims.add("iat");
|
|
70
|
+
for (const claimName of allRequiredClaims) {
|
|
71
|
+
if (!(claimName in jwtClaims)) missingClaims.add(claimName);
|
|
72
|
+
}
|
|
73
|
+
if (missingClaims.size > 0) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Missing required JWT Claims: ${[...missingClaims].join(", ")}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (options.issuer) {
|
|
79
|
+
const expectedIssuers = maybeArray(options.issuer);
|
|
80
|
+
if (!jwtClaims.iss || !expectedIssuers.includes(jwtClaims.iss)) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Invalid JWT "iss" (Issuer) Claim: Expected ${expectedIssuers.join(" or ")}, got ${jwtClaims.iss}`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (options.subject && jwtClaims.sub !== options.subject) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Invalid JWT "sub" (Subject) Claim: Expected ${options.subject}, got ${jwtClaims.sub}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (options.audience) {
|
|
92
|
+
const expectedAudiences = maybeArray(options.audience);
|
|
93
|
+
const claimAudience = maybeArray(jwtClaims.aud || []);
|
|
94
|
+
if (!claimAudience.some((aud) => expectedAudiences.includes(aud))) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Invalid JWT "aud" (Audience) Claim: Expected ${expectedAudiences.join(" or ")}, got ${claimAudience.join(", ")}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (typeof jwtClaims.nbf === "number" && jwtClaims.nbf > currentTime + clockTolerance) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`JWT "nbf" (Not Before) Claim validation failed: Token is not yet valid (nbf: ${new Date(jwtClaims.nbf * 1e3).toISOString()})`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (typeof jwtClaims.exp === "number" && jwtClaims.exp <= currentTime - clockTolerance) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`JWT "exp" (Expiration Time) Claim validation failed: Token has expired (exp: ${new Date(jwtClaims.exp * 1e3).toISOString()})`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
if (options.maxTokenAge) {
|
|
111
|
+
if (typeof jwtClaims.iat !== "number") {
|
|
112
|
+
throw new TypeError(
|
|
113
|
+
'JWT "iat" (Issued At) Claim must be a number when maxTokenAge is set.'
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (jwtClaims.iat > currentTime + clockTolerance) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`JWT "iat" (Issued At) Claim validation failed: Token was issued in the future (iat: ${new Date(jwtClaims.iat * 1e3).toISOString()})`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (jwtClaims.iat < currentTime - options.maxTokenAge - clockTolerance) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`JWT "iat" (Issued At) Claim validation failed: Token is too old (maxTokenAge: ${options.maxTokenAge}s, iat: ${new Date(jwtClaims.iat * 1e3).toISOString()})`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function validateCriticalHeadersJWS(protectedHeader, requiredHeaders = []) {
|
|
129
|
+
if (!protectedHeader.crit) return;
|
|
130
|
+
const missingHeaderParams = /* @__PURE__ */ new Set();
|
|
131
|
+
const recognizedParams = /* @__PURE__ */ new Set([
|
|
132
|
+
...requiredHeaders,
|
|
133
|
+
"alg",
|
|
134
|
+
"typ",
|
|
135
|
+
"cty",
|
|
136
|
+
"kid",
|
|
137
|
+
"jwk",
|
|
138
|
+
"jku",
|
|
139
|
+
"x5c",
|
|
140
|
+
"x5t",
|
|
141
|
+
"x5u",
|
|
142
|
+
"b64"
|
|
143
|
+
]);
|
|
144
|
+
for (const param of protectedHeader.crit) {
|
|
145
|
+
if (recognizedParams.has(param) && (param in protectedHeader || param === "b64")) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
missingHeaderParams.add(param);
|
|
149
|
+
}
|
|
150
|
+
if (missingHeaderParams.size > 0) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Missing critical header parameters: ${[...missingHeaderParams].join(", ")}`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function validateCriticalHeadersJWE(protectedHeader, understoodFromOptions) {
|
|
157
|
+
if (protectedHeader.crit && !understoodFromOptions) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Unprocessed critical header parameters: ${protectedHeader.crit.join(", ")}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (!protectedHeader.crit) return;
|
|
163
|
+
const understoodParams = /* @__PURE__ */ new Set([
|
|
164
|
+
...understoodFromOptions || [],
|
|
165
|
+
// JWE specific standard headers:
|
|
166
|
+
"alg",
|
|
167
|
+
"enc",
|
|
168
|
+
"typ",
|
|
169
|
+
"cty",
|
|
170
|
+
"kid",
|
|
171
|
+
"jwk",
|
|
172
|
+
"jku",
|
|
173
|
+
"x5c",
|
|
174
|
+
"x5t",
|
|
175
|
+
"x5u",
|
|
176
|
+
"iv",
|
|
177
|
+
"tag",
|
|
178
|
+
"p2s",
|
|
179
|
+
"p2c",
|
|
180
|
+
"epk",
|
|
181
|
+
"apu",
|
|
182
|
+
"apv"
|
|
183
|
+
]);
|
|
184
|
+
for (const critParam of protectedHeader.crit) {
|
|
185
|
+
if (!Object.prototype.hasOwnProperty.call(protectedHeader, critParam)) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`Critical header parameter "${critParam}" listed in "crit" but not present in the protected header.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
if (!understoodParams.has(critParam)) {
|
|
191
|
+
throw new Error(`Unprocessed critical header parameters: ${critParam}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const textEncoder = /* @__PURE__ */ new TextEncoder();
|
|
197
|
+
const textDecoder = /* @__PURE__ */ new TextDecoder();
|
|
198
|
+
function base64Encode(data) {
|
|
199
|
+
const encodedData = data instanceof Uint8Array ? data : textEncoder.encode(data);
|
|
200
|
+
if (Uint8Array.prototype.toBase64) {
|
|
201
|
+
return encodedData.toBase64();
|
|
202
|
+
}
|
|
203
|
+
return btoa(String.fromCodePoint(...encodedData));
|
|
204
|
+
}
|
|
205
|
+
function base64UrlEncode(data) {
|
|
206
|
+
const encodedData = data instanceof Uint8Array ? data : textEncoder.encode(data);
|
|
207
|
+
if (Uint8Array.prototype.toBase64) {
|
|
208
|
+
return encodedData.toBase64({ alphabet: "base64url", omitPadding: true });
|
|
209
|
+
}
|
|
210
|
+
return btoa(String.fromCodePoint(...encodedData)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
211
|
+
}
|
|
212
|
+
function base64Decode(str, toString) {
|
|
213
|
+
const decodeToString = toString !== false;
|
|
214
|
+
if (!str) {
|
|
215
|
+
return decodeToString ? "" : new Uint8Array(0);
|
|
216
|
+
}
|
|
217
|
+
const data = Uint8Array.fromBase64 ? (
|
|
218
|
+
// @ts-expect-error
|
|
219
|
+
Uint8Array.fromBase64(str)
|
|
220
|
+
) : Uint8Array.from(atob(str), (b) => b.codePointAt(0));
|
|
221
|
+
return decodeToString ? textDecoder.decode(data) : data;
|
|
222
|
+
}
|
|
223
|
+
function base64UrlDecode(str, toString) {
|
|
224
|
+
const decodeToString = toString !== false;
|
|
225
|
+
if (!str) {
|
|
226
|
+
return decodeToString ? "" : new Uint8Array(0);
|
|
227
|
+
}
|
|
228
|
+
let data;
|
|
229
|
+
if (Uint8Array.fromBase64) {
|
|
230
|
+
data = Uint8Array.fromBase64(str, { alphabet: "base64url" });
|
|
231
|
+
} else {
|
|
232
|
+
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
233
|
+
while (str.length % 4) str += "=";
|
|
234
|
+
data = Uint8Array.from(atob(str), (b) => b.codePointAt(0));
|
|
235
|
+
}
|
|
236
|
+
return decodeToString ? textDecoder.decode(data) : data;
|
|
237
|
+
}
|
|
238
|
+
function randomBytes(length) {
|
|
239
|
+
return crypto.getRandomValues(new Uint8Array(length));
|
|
240
|
+
}
|
|
241
|
+
function concatUint8Arrays(...arrays) {
|
|
242
|
+
const totalLength = arrays.reduce((length, arr) => length + arr.length, 0);
|
|
243
|
+
const result = new Uint8Array(totalLength);
|
|
244
|
+
let offset = 0;
|
|
245
|
+
for (const arr of arrays) {
|
|
246
|
+
result.set(arr, offset);
|
|
247
|
+
offset += arr.length;
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
function maybeArray(item) {
|
|
252
|
+
return Array.isArray(item) ? item : [item];
|
|
253
|
+
}
|
|
254
|
+
function isJWK(key) {
|
|
255
|
+
return typeof key === "object" && key !== null && "kty" in key && typeof key.kty === "string";
|
|
256
|
+
}
|
|
257
|
+
function isJWKSet(key) {
|
|
258
|
+
return key && typeof key === "object" && "keys" in key && Array.isArray(key.keys);
|
|
259
|
+
}
|
|
260
|
+
function assertCryptoKey(key) {
|
|
261
|
+
if (!isCryptoKey(key)) {
|
|
262
|
+
throw new Error("CryptoKey instance expected");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function isCryptoKey(key) {
|
|
266
|
+
return key?.[Symbol.toStringTag] === "CryptoKey";
|
|
267
|
+
}
|
|
268
|
+
const isCryptoKeyPair = (key) => key && typeof key === "object" && isCryptoKey(key.publicKey) && isCryptoKey(key.privateKey);
|
|
269
|
+
|
|
270
|
+
const index = {
|
|
271
|
+
__proto__: null,
|
|
272
|
+
applyTypCtyDefaults: applyTypCtyDefaults,
|
|
273
|
+
assertCryptoKey: assertCryptoKey,
|
|
274
|
+
base64Decode: base64Decode,
|
|
275
|
+
base64Encode: base64Encode,
|
|
276
|
+
base64UrlDecode: base64UrlDecode,
|
|
277
|
+
base64UrlEncode: base64UrlEncode,
|
|
278
|
+
computeJwtTimeClaims: computeJwtTimeClaims,
|
|
279
|
+
concatUint8Arrays: concatUint8Arrays,
|
|
280
|
+
decodeMaybeJsonString: decodeMaybeJsonString,
|
|
281
|
+
decodePayloadFromB64UrlSegment: decodePayloadFromB64UrlSegment,
|
|
282
|
+
decodePayloadFromBytes: decodePayloadFromBytes,
|
|
283
|
+
getPlaintextBytes: getPlaintextBytes,
|
|
284
|
+
isCryptoKey: isCryptoKey,
|
|
285
|
+
isCryptoKeyPair: isCryptoKeyPair,
|
|
286
|
+
isJWK: isJWK,
|
|
287
|
+
isJWKSet: isJWKSet,
|
|
288
|
+
isJsonContent: isJsonContent,
|
|
289
|
+
maybeArray: maybeArray,
|
|
290
|
+
randomBytes: randomBytes,
|
|
291
|
+
textDecoder: textDecoder,
|
|
292
|
+
textEncoder: textEncoder,
|
|
293
|
+
validateCriticalHeadersJWE: validateCriticalHeadersJWE,
|
|
294
|
+
validateCriticalHeadersJWS: validateCriticalHeadersJWS,
|
|
295
|
+
validateJwtClaims: validateJwtClaims
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export { isJWK as a, applyTypCtyDefaults as b, computeJwtTimeClaims as c, base64UrlEncode as d, textDecoder as e, base64UrlDecode as f, isJWKSet as g, decodePayloadFromB64UrlSegment as h, index as i, validateJwtClaims as j, concatUint8Arrays as k, assertCryptoKey as l, isCryptoKey as m, getPlaintextBytes as n, decodePayloadFromBytes as o, validateCriticalHeadersJWE as p, base64Decode as q, randomBytes as r, base64Encode as s, textEncoder as t, maybeArray as u, validateCriticalHeadersJWS as v, isCryptoKeyPair as w, isJsonContent as x, decodeMaybeJsonString as y };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { G as GenerateKeyAlgorithm, a as GenerateKeyOptions, b as GenerateKeyReturn, x as JWK_PBES2, D as DeriveKeyOptions, c as DeriveKeyReturn, l as JWK_oct, m as JWK, K as KeyManagementAlgorithm, W as WrapKeyOptions, e as WrapKeyResult, U as UnwrapKeyOptions, F as JWKPEMAlgorithm, n as JWKSet, C as CompositeKey, d as ContentEncryptionAlgorithm, E as JWKAlgorithm, J as JWKParameters, v as JWK_AES_CBC_HMAC, w as JWK_AES_GCM, u as JWK_AES_GCM_KW, t as JWK_AES_KW, B as JWK_Asymmetric_Algorithm, h as JWK_EC, y as JWK_ECDH_ES, r as JWK_ECDSA, g as JWK_EC_Private, f as JWK_EC_Public, z as JWK_ED, o as JWK_HMAC, k as JWK_RSA, s as JWK_RSA_ENC, q as JWK_RSA_PSS, j as JWK_RSA_Private, i as JWK_RSA_Public, p as JWK_RSA_SIGN, A as JWK_Symmetric_Algorithm } from './unjwt.
|
|
2
|
-
import { J as JoseHeaderParameters } from './unjwt.BvIkEGGz.mjs';
|
|
1
|
+
import { G as GenerateKeyAlgorithm, a as GenerateKeyOptions, b as GenerateKeyReturn, x as JWK_PBES2, D as DeriveKeyOptions, c as DeriveKeyReturn, l as JWK_oct, m as JWK, K as KeyManagementAlgorithm, W as WrapKeyOptions, e as WrapKeyResult, U as UnwrapKeyOptions, F as JWKPEMAlgorithm, n as JWKSet, H as JoseHeaderParameters, C as CompositeKey, d as ContentEncryptionAlgorithm, E as JWKAlgorithm, J as JWKParameters, v as JWK_AES_CBC_HMAC, w as JWK_AES_GCM, u as JWK_AES_GCM_KW, t as JWK_AES_KW, B as JWK_Asymmetric_Algorithm, h as JWK_EC, y as JWK_ECDH_ES, r as JWK_ECDSA, g as JWK_EC_Private, f as JWK_EC_Public, z as JWK_ED, o as JWK_HMAC, k as JWK_RSA, s as JWK_RSA_ENC, q as JWK_RSA_PSS, j as JWK_RSA_Private, i as JWK_RSA_Public, p as JWK_RSA_SIGN, A as JWK_Symmetric_Algorithm } from './unjwt.CN1C8TlR.mjs';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* This is a fork of Jose library's utility functions.
|
|
@@ -31,7 +30,7 @@ declare function generateKey<TAlg extends GenerateKeyAlgorithm, TOptions extends
|
|
|
31
30
|
* @param options Configuration options including salt and iterations.
|
|
32
31
|
* @returns A Promise resolving to the derived key (CryptoKey) or its JWK_oct representation.
|
|
33
32
|
*/
|
|
34
|
-
declare function deriveKeyFromPassword<TAlg extends JWK_PBES2, TOptions extends DeriveKeyOptions>(password: string | Uint8Array
|
|
33
|
+
declare function deriveKeyFromPassword<TAlg extends JWK_PBES2, TOptions extends DeriveKeyOptions>(password: string | Uint8Array<ArrayBuffer>, alg: TAlg, options: TOptions): Promise<DeriveKeyReturn<TOptions>>;
|
|
35
34
|
/**
|
|
36
35
|
* Imports a key from various formats (CryptoKey, JWK, Uint8Array).
|
|
37
36
|
*
|
|
@@ -44,11 +43,11 @@ declare function deriveKeyFromPassword<TAlg extends JWK_PBES2, TOptions extends
|
|
|
44
43
|
* @param alg The algorithm hint, required when importing asymmetric JWKs.
|
|
45
44
|
* @returns A Promise resolving to the imported key as CryptoKey or Uint8Array.
|
|
46
45
|
*/
|
|
47
|
-
declare function importKey(key: string): Promise<Uint8Array
|
|
48
|
-
declare function importKey(key: Uint8Array): Promise<Uint8Array
|
|
46
|
+
declare function importKey(key: string): Promise<Uint8Array<ArrayBuffer>>;
|
|
47
|
+
declare function importKey(key: Uint8Array<ArrayBuffer>): Promise<Uint8Array<ArrayBuffer>>;
|
|
49
48
|
declare function importKey(key: CryptoKey): Promise<CryptoKey>;
|
|
50
|
-
declare function importKey(key: JWK_oct): Promise<Uint8Array
|
|
51
|
-
declare function importKey(key: CryptoKey | JWK | Uint8Array | string, alg?: string): Promise<CryptoKey | Uint8Array
|
|
49
|
+
declare function importKey(key: JWK_oct): Promise<Uint8Array<ArrayBuffer>>;
|
|
50
|
+
declare function importKey(key: CryptoKey | JWK | Uint8Array<ArrayBuffer> | string, alg?: string): Promise<CryptoKey | Uint8Array<ArrayBuffer>>;
|
|
52
51
|
/**
|
|
53
52
|
* Exports a CryptoKey to a JWK (JSON Web Key) format.
|
|
54
53
|
*
|
|
@@ -56,7 +55,7 @@ declare function importKey(key: CryptoKey | JWK | Uint8Array | string, alg?: str
|
|
|
56
55
|
* @param jwk Optional partial JWK to merge with the exported key, allowing overrides.
|
|
57
56
|
* @returns A Promise resolving to the exported JWK.
|
|
58
57
|
*/
|
|
59
|
-
declare function exportKey(key: CryptoKey, jwk?: Partial<JWK>): Promise<
|
|
58
|
+
declare function exportKey<T extends JWK>(key: CryptoKey, jwk?: Partial<JWK>): Promise<T>;
|
|
60
59
|
/**
|
|
61
60
|
* Wraps a Content Encryption Key (CEK) using the specified algorithm and wrapping key.
|
|
62
61
|
*
|
|
@@ -66,7 +65,7 @@ declare function exportKey(key: CryptoKey, jwk?: Partial<JWK>): Promise<JWK>;
|
|
|
66
65
|
* @param options Additional options required by certain algorithms (e.g., p2s, p2c for PBES2).
|
|
67
66
|
* @returns A Promise resolving to an object containing the wrapped key and any necessary parameters (iv, tag, epk, etc.).
|
|
68
67
|
*/
|
|
69
|
-
declare function wrapKey(alg: KeyManagementAlgorithm, keyToWrap: CryptoKey | Uint8Array
|
|
68
|
+
declare function wrapKey(alg: KeyManagementAlgorithm, keyToWrap: CryptoKey | Uint8Array<ArrayBuffer>, wrappingKey: CryptoKey | JWK | string | Uint8Array<ArrayBuffer>, options?: WrapKeyOptions): Promise<WrapKeyResult>;
|
|
70
69
|
/**
|
|
71
70
|
* Unwraps a Content Encryption Key (CEK) using the specified algorithm and unwrapping key.
|
|
72
71
|
*
|
|
@@ -76,9 +75,9 @@ declare function wrapKey(alg: KeyManagementAlgorithm, keyToWrap: CryptoKey | Uin
|
|
|
76
75
|
* @param options Additional options required by certain algorithms (e.g., iv, tag, p2s, p2c, epk).
|
|
77
76
|
* @returns A Promise resolving to the unwrapped key (CEK) as a CryptoKey or Uint8Array.
|
|
78
77
|
*/
|
|
79
|
-
declare function unwrapKey<T extends boolean | undefined = undefined>(alg: KeyManagementAlgorithm, wrappedKey: Uint8Array
|
|
78
|
+
declare function unwrapKey<T extends boolean | undefined = undefined>(alg: KeyManagementAlgorithm, wrappedKey: Uint8Array<ArrayBuffer>, unwrappingKey: CryptoKey | JWK | string | Uint8Array<ArrayBuffer>, options?: UnwrapKeyOptions & {
|
|
80
79
|
returnAs?: T;
|
|
81
|
-
}): Promise<T extends false ? Uint8Array : CryptoKey>;
|
|
80
|
+
}): Promise<T extends false ? Uint8Array<ArrayBuffer> : CryptoKey>;
|
|
82
81
|
/**
|
|
83
82
|
* Imports a key from a PEM-encoded string and converts it to a JWK.
|
|
84
83
|
*
|
|
@@ -90,7 +89,7 @@ declare function unwrapKey<T extends boolean | undefined = undefined>(alg: KeyMa
|
|
|
90
89
|
* @param jwkExtras Additional properties to merge into the resulting JWK.
|
|
91
90
|
* @returns A Promise resolving to the imported key as a JWK.
|
|
92
91
|
*/
|
|
93
|
-
declare function importJWKFromPEM(pem: string, pemType: "pkcs8" | "spki" | "x509", alg: JWKPEMAlgorithm, importOptions?: KeyImportOptions, jwkExtras?: Partial<JWK>): Promise<
|
|
92
|
+
declare function importJWKFromPEM<T extends JWK>(pem: string, pemType: "pkcs8" | "spki" | "x509", alg: JWKPEMAlgorithm, importOptions?: KeyImportOptions, jwkExtras?: Partial<JWK>): Promise<T>;
|
|
94
93
|
/**
|
|
95
94
|
* Exports a JWK to a PEM-encoded string.
|
|
96
95
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as checkEncCryptoKey, u as uint32be, b as generateCEK, e as encryptIV, w as wrap, k as keyToJWK, d as bitLengthCEK, f as jwkTokey, i as importKey, h as generateIV, l as encrypt$1, m as unwrapKey, n as decrypt$1 } from './unjwt.
|
|
2
|
-
import {
|
|
3
|
-
import { c as checkKeyLength } from './unjwt.
|
|
1
|
+
import { a as checkEncCryptoKey, u as uint32be, b as generateCEK, e as encryptIV, w as wrap, k as keyToJWK, d as bitLengthCEK, f as jwkTokey, i as importKey, h as generateIV, l as encrypt$1, m as unwrapKey, n as decrypt$1 } from './unjwt.DuBBF25X.mjs';
|
|
2
|
+
import { k as concatUint8Arrays, t as textEncoder, l as assertCryptoKey, d as base64UrlEncode, m as isCryptoKey, a as isJWK, f as base64UrlDecode, r as randomBytes, b as applyTypCtyDefaults, c as computeJwtTimeClaims, n as getPlaintextBytes, o as decodePayloadFromBytes, p as validateCriticalHeadersJWE } from './unjwt.Ce8yMcp_.mjs';
|
|
3
|
+
import { c as checkKeyLength } from './unjwt.C_D0RMCp.mjs';
|
|
4
4
|
|
|
5
5
|
function lengthAndInput(input) {
|
|
6
6
|
return concatUint8Arrays(uint32be(input.length), input);
|
|
@@ -218,7 +218,6 @@ async function encrypt(payload, key, options = {}) {
|
|
|
218
218
|
if (!enc) {
|
|
219
219
|
enc = isJWK(key) && "enc" in key ? key.enc : "A128GCM";
|
|
220
220
|
}
|
|
221
|
-
const plaintextBytes = getPlaintextBytes(payload);
|
|
222
221
|
const jweKeyManagementParams = {};
|
|
223
222
|
if (keyManagementIV) jweKeyManagementParams.iv = keyManagementIV;
|
|
224
223
|
if (p2s) jweKeyManagementParams.p2s = p2s;
|
|
@@ -252,13 +251,15 @@ async function encrypt(payload, key, options = {}) {
|
|
|
252
251
|
alg,
|
|
253
252
|
enc
|
|
254
253
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
254
|
+
const protectedHeader = applyTypCtyDefaults(jweProtectedHeader, payload);
|
|
255
|
+
const computedPayload = computeJwtTimeClaims(
|
|
256
|
+
payload,
|
|
257
|
+
protectedHeader.typ,
|
|
258
|
+
options.expiresIn,
|
|
259
|
+
options.currentDate
|
|
260
|
+
);
|
|
261
|
+
const plaintextBytes = getPlaintextBytes(computedPayload || payload);
|
|
262
|
+
const protectedHeaderSerialized = JSON.stringify(protectedHeader);
|
|
262
263
|
const protectedHeaderEncoded = base64UrlEncode(protectedHeaderSerialized);
|
|
263
264
|
const aadBytes = textEncoder.encode(protectedHeaderEncoded);
|
|
264
265
|
const contentIVBytes = providedContentIV ?? generateIV(enc);
|
|
@@ -345,7 +346,7 @@ async function decrypt(jwe, key, options) {
|
|
|
345
346
|
keyUsage: options?.keyUsage,
|
|
346
347
|
extractable: options?.extractable,
|
|
347
348
|
returnAs: false
|
|
348
|
-
// Returning CEK as Uint8Array
|
|
349
|
+
// Returning CEK as Uint8Array<ArrayBuffer>
|
|
349
350
|
};
|
|
350
351
|
const cekBytes = await unwrapKey(
|
|
351
352
|
alg,
|
|
@@ -362,66 +363,15 @@ async function decrypt(jwe, key, options) {
|
|
|
362
363
|
contentAuthTagBytes,
|
|
363
364
|
aadBytes
|
|
364
365
|
);
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
try {
|
|
375
|
-
payload = JSON.parse(decodedString);
|
|
376
|
-
} catch {
|
|
377
|
-
payload = decodedString;
|
|
378
|
-
}
|
|
379
|
-
} else {
|
|
380
|
-
payload = decodedString;
|
|
381
|
-
}
|
|
382
|
-
} else {
|
|
383
|
-
payload = decodedString;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
if (options?.critical && protectedHeader.crit) {
|
|
387
|
-
const understoodParams = /* @__PURE__ */ new Set([
|
|
388
|
-
...options.critical || [],
|
|
389
|
-
// JWE specific standard headers:
|
|
390
|
-
"alg",
|
|
391
|
-
"enc",
|
|
392
|
-
"typ",
|
|
393
|
-
"cty",
|
|
394
|
-
"kid",
|
|
395
|
-
"jwk",
|
|
396
|
-
"jku",
|
|
397
|
-
"x5c",
|
|
398
|
-
"x5t",
|
|
399
|
-
"x5u",
|
|
400
|
-
"iv",
|
|
401
|
-
"tag",
|
|
402
|
-
"p2s",
|
|
403
|
-
"p2c",
|
|
404
|
-
"epk",
|
|
405
|
-
"apu",
|
|
406
|
-
"apv"
|
|
407
|
-
]);
|
|
408
|
-
for (const critParam of protectedHeader.crit) {
|
|
409
|
-
if (!Object.prototype.hasOwnProperty.call(protectedHeader, critParam)) {
|
|
410
|
-
throw new Error(
|
|
411
|
-
`Critical header parameter "${critParam}" listed in "crit" but not present in the protected header.`
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
if (!understoodParams.has(critParam)) {
|
|
415
|
-
throw new Error(
|
|
416
|
-
`Critical header parameter not understood: ${critParam}`
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
} else if (!options?.critical && protectedHeader.crit) {
|
|
421
|
-
throw new Error(
|
|
422
|
-
`Unprocessed critical header parameters: ${protectedHeader.crit.join(", ")}`
|
|
423
|
-
);
|
|
424
|
-
}
|
|
366
|
+
const payload = decodePayloadFromBytes(
|
|
367
|
+
plaintextBytes,
|
|
368
|
+
protectedHeader,
|
|
369
|
+
options?.forceUint8Array
|
|
370
|
+
);
|
|
371
|
+
validateCriticalHeadersJWE(protectedHeader, [
|
|
372
|
+
...options?.critical || [],
|
|
373
|
+
...options?.requiredHeaders || []
|
|
374
|
+
]);
|
|
425
375
|
return {
|
|
426
376
|
payload,
|
|
427
377
|
protectedHeader,
|
|
@@ -429,20 +379,6 @@ async function decrypt(jwe, key, options) {
|
|
|
429
379
|
aad: aadBytes
|
|
430
380
|
};
|
|
431
381
|
}
|
|
432
|
-
function getPlaintextBytes(payload) {
|
|
433
|
-
if (payload instanceof Uint8Array) {
|
|
434
|
-
return payload;
|
|
435
|
-
}
|
|
436
|
-
if (typeof payload === "string") {
|
|
437
|
-
return textEncoder.encode(payload);
|
|
438
|
-
}
|
|
439
|
-
if (typeof payload === "object" && payload !== null) {
|
|
440
|
-
return textEncoder.encode(JSON.stringify(payload));
|
|
441
|
-
}
|
|
442
|
-
throw new TypeError(
|
|
443
|
-
"Plaintext must be a string, Uint8Array, or a JSON-serializable object."
|
|
444
|
-
);
|
|
445
|
-
}
|
|
446
382
|
|
|
447
383
|
const jwe = {
|
|
448
384
|
__proto__: null,
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { i as importKey, g as getJWKFromSet } from './unjwt.DuBBF25X.mjs';
|
|
2
|
+
import { a as isJWK, b as applyTypCtyDefaults, c as computeJwtTimeClaims, d as base64UrlEncode, t as textEncoder, e as textDecoder, f as base64UrlDecode, g as isJWKSet, h as decodePayloadFromB64UrlSegment, v as validateCriticalHeadersJWS, j as validateJwtClaims } from './unjwt.Ce8yMcp_.mjs';
|
|
3
|
+
import { s as sign$1, v as verify$1 } from './unjwt.C_D0RMCp.mjs';
|
|
4
|
+
|
|
5
|
+
async function sign(payload, key, options = {}) {
|
|
6
|
+
const { protectedHeader: additionalProtectedHeader } = options;
|
|
7
|
+
let { alg } = options;
|
|
8
|
+
if (!alg) {
|
|
9
|
+
if (isJWK(key) && key.alg) {
|
|
10
|
+
alg = key.alg;
|
|
11
|
+
} else {
|
|
12
|
+
throw new TypeError('JWS "alg" (Algorithm) must be provided in options');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
validateKeyLength(key, alg);
|
|
16
|
+
const signingKey = await importKey(key, alg);
|
|
17
|
+
const protectedHeader = {
|
|
18
|
+
...additionalProtectedHeader,
|
|
19
|
+
...isJWK(key) && key.kid ? { kid: additionalProtectedHeader?.kid || key.kid } : {},
|
|
20
|
+
// Include kid if available
|
|
21
|
+
alg,
|
|
22
|
+
typ: additionalProtectedHeader?.typ
|
|
23
|
+
};
|
|
24
|
+
applyTypCtyDefaults(protectedHeader, payload);
|
|
25
|
+
if (protectedHeader.b64 === true) {
|
|
26
|
+
delete protectedHeader.b64;
|
|
27
|
+
}
|
|
28
|
+
const computedPayload = computeJwtTimeClaims(
|
|
29
|
+
payload,
|
|
30
|
+
protectedHeader.typ,
|
|
31
|
+
options.expiresIn,
|
|
32
|
+
options.currentDate
|
|
33
|
+
);
|
|
34
|
+
const protectedHeaderString = JSON.stringify(protectedHeader);
|
|
35
|
+
const protectedHeaderEncoded = base64UrlEncode(protectedHeaderString);
|
|
36
|
+
let payloadBytes;
|
|
37
|
+
if (payload instanceof Uint8Array) {
|
|
38
|
+
payloadBytes = payload;
|
|
39
|
+
} else if (typeof payload === "string") {
|
|
40
|
+
payloadBytes = textEncoder.encode(payload);
|
|
41
|
+
} else if (typeof payload === "object" && payload !== null) {
|
|
42
|
+
payloadBytes = textEncoder.encode(
|
|
43
|
+
JSON.stringify(computedPayload || payload)
|
|
44
|
+
);
|
|
45
|
+
} else {
|
|
46
|
+
throw new TypeError(
|
|
47
|
+
"Payload must be a string, Uint8Array, or a JSON-serializable object."
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const useB64 = protectedHeader.b64 !== false;
|
|
51
|
+
const payloadEncoded = useB64 ? base64UrlEncode(payloadBytes) : textDecoder.decode(payloadBytes);
|
|
52
|
+
const signingInputString = `${protectedHeaderEncoded}.${payloadEncoded}`;
|
|
53
|
+
const signingInputBytes = textEncoder.encode(signingInputString);
|
|
54
|
+
const signatureBytes = await sign$1(alg, signingKey, signingInputBytes);
|
|
55
|
+
const signatureEncoded = base64UrlEncode(signatureBytes);
|
|
56
|
+
return `${signingInputString}.${signatureEncoded}`;
|
|
57
|
+
}
|
|
58
|
+
async function verify(jws, key, options = {}) {
|
|
59
|
+
const parts = jws.split(".");
|
|
60
|
+
if (parts.length !== 3) {
|
|
61
|
+
throw new Error("Invalid JWS: Must contain three parts separated by dots.");
|
|
62
|
+
}
|
|
63
|
+
const [protectedHeaderEncoded, payloadEncoded, signatureEncoded] = parts;
|
|
64
|
+
let protectedHeader;
|
|
65
|
+
try {
|
|
66
|
+
const protectedHeaderString = base64UrlDecode(protectedHeaderEncoded);
|
|
67
|
+
protectedHeader = JSON.parse(protectedHeaderString);
|
|
68
|
+
} catch (error_) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Invalid JWS: Protected header is not valid Base64URL or JSON (${error_ instanceof Error ? error_.message : error_})`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (!protectedHeader || typeof protectedHeader !== "object" || !protectedHeader.alg) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
'Invalid JWS: Protected header must be an object with an "alg" property.'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
const alg = protectedHeader.alg;
|
|
79
|
+
if (options.algorithms && !options.algorithms.includes(alg)) {
|
|
80
|
+
throw new Error(`Algorithm not allowed: ${alg}`);
|
|
81
|
+
}
|
|
82
|
+
if (options.typ && protectedHeader.typ !== options.typ) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Invalid JWS: "typ" (Type) Header Parameter mismatch. Expected "${options.typ}", got "${protectedHeader.typ}".`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
let signatureBytes;
|
|
88
|
+
try {
|
|
89
|
+
signatureBytes = base64UrlDecode(signatureEncoded, false);
|
|
90
|
+
} catch (error_) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Invalid JWS: Signature is not valid Base64URL (${error_ instanceof Error ? error_.message : error_})`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const keyInput = typeof key === "function" ? await key(protectedHeader, jws) : key;
|
|
96
|
+
const resolvedKey = isJWKSet(
|
|
97
|
+
keyInput
|
|
98
|
+
) ? getJWKFromSet(keyInput, protectedHeader) : keyInput;
|
|
99
|
+
const verificationKey = await importKey(resolvedKey, alg);
|
|
100
|
+
const signingInputString = `${protectedHeaderEncoded}.${payloadEncoded}`;
|
|
101
|
+
const signingInputBytes = textEncoder.encode(signingInputString);
|
|
102
|
+
const isValid = await verify$1(
|
|
103
|
+
alg,
|
|
104
|
+
verificationKey,
|
|
105
|
+
signatureBytes,
|
|
106
|
+
signingInputBytes
|
|
107
|
+
);
|
|
108
|
+
if (!isValid) {
|
|
109
|
+
throw new Error("JWS signature verification failed.");
|
|
110
|
+
}
|
|
111
|
+
const useB64 = protectedHeader.b64 !== false;
|
|
112
|
+
let payload;
|
|
113
|
+
try {
|
|
114
|
+
payload = useB64 ? decodePayloadFromB64UrlSegment(
|
|
115
|
+
payloadEncoded,
|
|
116
|
+
protectedHeader,
|
|
117
|
+
options.forceUint8Array
|
|
118
|
+
) : options.forceUint8Array ? textEncoder.encode(payloadEncoded) : payloadEncoded;
|
|
119
|
+
} catch (error_) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`Invalid JWS: Payload decoding failed (${error_ instanceof Error ? error_.message : error_})`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
validateCriticalHeadersJWS(protectedHeader, [
|
|
125
|
+
...options.critical || [],
|
|
126
|
+
...options.requiredHeaders || []
|
|
127
|
+
]);
|
|
128
|
+
if (payload && typeof payload === "object" && (protectedHeader.typ === "at+jwt" || protectedHeader.typ === "JWT") && !options.forceUint8Array) {
|
|
129
|
+
validateJwtClaims(payload, options);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
payload,
|
|
133
|
+
protectedHeader
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function validateKeyLength(key, alg) {
|
|
137
|
+
if (!alg || isJWK(key)) return;
|
|
138
|
+
if (alg.startsWith("HS") && key instanceof Uint8Array) {
|
|
139
|
+
const algLength = Number.parseInt(alg.slice(2)) / 8;
|
|
140
|
+
if (key.length < algLength) {
|
|
141
|
+
throw new TypeError(
|
|
142
|
+
`${alg} requires key length to be ${algLength} bytes or larger`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
} else if ((alg.startsWith("RS") || alg.startsWith("PS")) && key instanceof CryptoKey) {
|
|
146
|
+
const { modulusLength } = key.algorithm;
|
|
147
|
+
if (typeof modulusLength !== "number" || modulusLength < 2048) {
|
|
148
|
+
throw new TypeError(
|
|
149
|
+
`${alg} requires key modulusLength to be 2048 bits or larger`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const jws = {
|
|
156
|
+
__proto__: null,
|
|
157
|
+
sign: sign,
|
|
158
|
+
verify: verify
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export { jws as j, sign as s, verify as v };
|