unjwt 0.7.1 → 0.7.3
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/_chunks/_internal.mjs +5 -5
- package/dist/_chunks/index.d.mts +42 -17
- package/dist/_chunks/jwe.d.mts +2 -2
- package/dist/_chunks/jwe.mjs +5 -5
- package/dist/_chunks/jwk.mjs +51 -35
- package/dist/_chunks/jws.d.mts +2 -2
- package/dist/_chunks/jws.mjs +6 -6
- package/dist/_chunks/libs/unsecure.d.mts +1 -1
- package/dist/_chunks/libs/unsecure.mjs +3 -3
- package/dist/_chunks/utils.mjs +8 -6
- package/dist/adapters/elysia/index.d.mts +244 -0
- package/dist/adapters/elysia/index.mjs +608 -0
- package/dist/adapters/h3v1/index.d.mts +120 -42
- package/dist/adapters/h3v1/index.mjs +18 -15
- package/dist/adapters/h3v2/index.d.mts +140 -20
- package/dist/adapters/h3v2/index.mjs +18 -15
- package/dist/core/jwe.d.mts +3 -3
- package/dist/core/jwe.mjs +2 -2
- package/dist/core/jwk.d.mts +10 -10
- package/dist/core/jwk.mjs +2 -2
- package/dist/core/jws.d.mts +3 -3
- package/dist/core/jws.mjs +2 -2
- package/dist/core/utils/index.d.mts +24 -8
- package/dist/core/utils/index.mjs +2 -2
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +4 -4
- package/package.json +34 -21
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { JWTError, decodePayloadFromB64UrlSegment, inferJWEAllowedAlgorithms, inferJWSAllowedAlgorithms, isCryptoKey, isCryptoKeyPair, isJWK, validateJwtClaims } from "./utils.mjs";
|
|
2
|
+
import { base64UrlDecode, safeJsonParse, textEncoder } from "./libs/unsecure.mjs";
|
|
3
|
+
import { assertOctKeyLength } from "./jwk.mjs";
|
|
3
4
|
function buildJWKSetFilter(header) {
|
|
4
5
|
const kid = header?.kid;
|
|
5
6
|
const alg = header?.alg;
|
|
@@ -35,8 +36,7 @@ function parseEphemeralKey(ephemeralKey) {
|
|
|
35
36
|
}
|
|
36
37
|
async function resolveSigningKey(alg, key, usage) {
|
|
37
38
|
if (key instanceof Uint8Array) {
|
|
38
|
-
|
|
39
|
-
if (key.length < minBytes) throw new JWTError(`${alg} requires a key of at least ${minBytes} bytes`, "ERR_JWK_INVALID");
|
|
39
|
+
assertOctKeyLength(key, alg);
|
|
40
40
|
return crypto.subtle.importKey("raw", key, {
|
|
41
41
|
name: "HMAC",
|
|
42
42
|
hash: `SHA-${alg.slice(-3)}`
|
|
@@ -85,4 +85,4 @@ function decodeJWSPayload(payloadSegment, useB64, forceUint8Array) {
|
|
|
85
85
|
if (useB64) return decodePayloadFromB64UrlSegment(payloadSegment, forceUint8Array);
|
|
86
86
|
return forceUint8Array ? textEncoder.encode(payloadSegment) : payloadSegment;
|
|
87
87
|
}
|
|
88
|
-
export {
|
|
88
|
+
export { JWE_ALG_CTX, JWS_ALG_CTX, buildJWKSetFilter, checkAlgAllowed, decodeJWSPayload, decodeProtectedHeader, parseEphemeralKey, resolveSigningKey, validateJwtClaimsIfJsonPayload };
|
package/dist/_chunks/index.d.mts
CHANGED
|
@@ -66,7 +66,12 @@ type GenerateKeyAlgorithm = Exclude<JWKAlgorithm, "none" | "dir" | JWK_PBES2>;
|
|
|
66
66
|
interface GenerateKeyOptions {
|
|
67
67
|
/** Key usages for the generated key(s). Note: For composite keys (CBC), default usages are applied separately. */
|
|
68
68
|
keyUsage?: KeyUsage[];
|
|
69
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Mark the key(s) as extractable. Defaults to true. Ignored when `toJWK` is set —
|
|
71
|
+
* the JWK output requires exporting the intermediate key. For long-lived asymmetric
|
|
72
|
+
* private keys that should never leave the runtime, prefer `false` (and omit `toJWK`):
|
|
73
|
+
* the key still signs/decrypts but its material cannot be exported.
|
|
74
|
+
*/
|
|
70
75
|
extractable?: boolean;
|
|
71
76
|
/** RSA modulus length. Defaults to 2048. */
|
|
72
77
|
modulusLength?: number;
|
|
@@ -84,7 +89,7 @@ interface GenerateKeyOptions {
|
|
|
84
89
|
type GenerateKeyReturnJWK<TAlg extends GenerateKeyAlgorithm> = TAlg extends JWK_Asymmetric_Algorithm ? JWK_Pair<TAlg> : TAlg extends JWK_AES_CBC_HMAC | JWK_Symmetric_Algorithm ? JWK_oct<TAlg> : never;
|
|
85
90
|
type GenerateKeyReturnCrypto<TAlg extends GenerateKeyAlgorithm> = TAlg extends JWK_AES_CBC_HMAC ? Uint8Array<ArrayBuffer> : TAlg extends JWK_Asymmetric_Algorithm ? CryptoKeyPair : CryptoKey;
|
|
86
91
|
type GenerateKeyReturn<TAlg extends GenerateKeyAlgorithm, TOptions extends GenerateKeyOptions> = TOptions["toJWK"] extends true ? GenerateKeyReturnJWK<TAlg> : GenerateKeyReturnCrypto<TAlg>;
|
|
87
|
-
type GenerateJWKOptions = Omit<GenerateKeyOptions, "toJWK">;
|
|
92
|
+
type GenerateJWKOptions = Omit<GenerateKeyOptions, "toJWK" | "extractable">;
|
|
88
93
|
type GenerateJWKReturn<TAlg extends GenerateKeyAlgorithm> = GenerateKeyReturnJWK<TAlg>;
|
|
89
94
|
/** Options for the deriveKeyFromPassword function. */
|
|
90
95
|
interface DeriveKeyOptions {
|
|
@@ -94,7 +99,7 @@ interface DeriveKeyOptions {
|
|
|
94
99
|
iterations: number;
|
|
95
100
|
/** Key usages for the derived key. Defaults to ["wrapKey", "unwrapKey"]. */
|
|
96
101
|
keyUsage?: KeyUsage[];
|
|
97
|
-
/** Mark the derived key as extractable. Defaults to false. */
|
|
102
|
+
/** Mark the derived key as extractable. Defaults to false. Ignored when `toJWK` is set — the JWK output requires exporting the derived key. */
|
|
98
103
|
extractable?: boolean;
|
|
99
104
|
/**
|
|
100
105
|
* Export the derived key as JWK_oct. When `true`, returns the derived key in
|
|
@@ -126,7 +131,15 @@ type WrappingKeyFor<A extends KeyManagementAlgorithm> = A extends JWK_RSA_ENC ?
|
|
|
126
131
|
type UnwrappingKeyFor<A extends KeyManagementAlgorithm> = A extends JWK_RSA_ENC ? CryptoKey | JWK_RSA_Private<A> : A extends JWK_ECDH_ES ? CryptoKey | JWK_EC_Private<A> | JWK_OKP_Private<A> : A extends JWK_PBES2 ? string | Uint8Array<ArrayBuffer> | JWK_oct<A> : A extends JWK_AES_KW ? CryptoKey | JWK_oct<A> : A extends JWK_AES_GCM_KW ? CryptoKey | JWK_oct<A | `A${"128" | "192" | "256"}GCM`> : A extends "dir" ? CryptoKey | JWK_oct | Uint8Array<ArrayBuffer> : never;
|
|
127
132
|
/** Options for the wrapKey function. */
|
|
128
133
|
interface WrapKeyOptions {
|
|
129
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Initialization Vector for AES-GCMKW. A fresh random IV is generated when
|
|
136
|
+
* not provided — production code should always omit this option.
|
|
137
|
+
*
|
|
138
|
+
* **Never reuse an IV and never derive it from external input.** A single
|
|
139
|
+
* IV reused under the same wrapping key breaks AES-GCM entirely (plaintext
|
|
140
|
+
* recovery and forgery). Provided only for tests and reproduction of known
|
|
141
|
+
* vectors in security research.
|
|
142
|
+
*/
|
|
130
143
|
iv?: Uint8Array<ArrayBuffer>;
|
|
131
144
|
/** PBES2 Salt value (p2s). Required for PBES2 algorithms. */
|
|
132
145
|
p2s?: Uint8Array<ArrayBuffer>;
|
|
@@ -228,35 +241,35 @@ interface UnwrapKeyOptions {
|
|
|
228
241
|
*/
|
|
229
242
|
interface JWKParameters<Alg extends string = string> {
|
|
230
243
|
/** JWK "kty" (Key Type) Parameter */
|
|
231
|
-
kty: string;
|
|
244
|
+
"kty": string;
|
|
232
245
|
/**
|
|
233
246
|
* JWK "alg" (Algorithm) Parameter
|
|
234
247
|
*
|
|
235
248
|
* @see {@link https://github.com/panva/jose/issues/210 Algorithm Key Requirements}
|
|
236
249
|
*/
|
|
237
|
-
alg?: Alg;
|
|
250
|
+
"alg"?: Alg;
|
|
238
251
|
/** JWK "key_ops" (Key Operations) Parameter */
|
|
239
|
-
key_ops?: KeyUsage[];
|
|
252
|
+
"key_ops"?: KeyUsage[];
|
|
240
253
|
/** JWK "ext" (Extractable) Parameter */
|
|
241
|
-
ext?: boolean;
|
|
254
|
+
"ext"?: boolean;
|
|
242
255
|
/** JWK "use" (Public Key Use) Parameter */
|
|
243
|
-
use?: string;
|
|
256
|
+
"use"?: string;
|
|
244
257
|
/** JWK "x5c" (X.509 Certificate Chain) Parameter */
|
|
245
|
-
x5c?: string[];
|
|
258
|
+
"x5c"?: string[];
|
|
246
259
|
/** JWK "x5t" (X.509 Certificate SHA-1 Thumbprint) Parameter */
|
|
247
|
-
x5t?: string;
|
|
260
|
+
"x5t"?: string;
|
|
248
261
|
/** JWK "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Parameter */
|
|
249
262
|
"x5t#S256"?: string;
|
|
250
263
|
/** JWK "x5u" (X.509 URL) Parameter */
|
|
251
|
-
x5u?: string;
|
|
264
|
+
"x5u"?: string;
|
|
252
265
|
/** JWK "kid" (Key ID) Parameter */
|
|
253
|
-
kid?: string;
|
|
266
|
+
"kid"?: string;
|
|
254
267
|
/**
|
|
255
268
|
* Non-standard JWK content encryption algorithm hint.
|
|
256
269
|
* When `alg` is `"dir"`, the library reads this field to infer the
|
|
257
270
|
* content encryption algorithm (`enc`) when it is not provided in options.
|
|
258
271
|
*/
|
|
259
|
-
enc?: ContentEncryptionAlgorithm;
|
|
272
|
+
"enc"?: ContentEncryptionAlgorithm;
|
|
260
273
|
}
|
|
261
274
|
/** Public EC JSON Web Keys */
|
|
262
275
|
interface JWK_EC_Public<Alg extends JWK_ECDSA | JWK_ECDH_ES | (string & {}) = string> extends JWKParameters<Alg> {
|
|
@@ -321,6 +334,8 @@ interface JWK_OKP_Private<Alg extends JWK_OKP_SIGN | JWK_ECDH_ES | (string & {})
|
|
|
321
334
|
type JWK_OKP<Alg extends JWK_OKP_SIGN | JWK_ECDH_ES | (string & {}) = string> = JWK_OKP_Public<Alg> | JWK_OKP_Private<Alg>;
|
|
322
335
|
/** oct JSON Web Keys */
|
|
323
336
|
interface JWK_oct<Alg extends JWK_HMAC | JWK_AES_KW | JWK_AES_GCM | JWK_AES_GCM_KW | JWK_AES_CBC_HMAC | JWK_PBES2 | "dir" | (string & {}) = string> extends JWKParameters<Alg> {
|
|
337
|
+
/** Oct JWK "kty" (Key Type) Parameter */
|
|
338
|
+
kty: "oct";
|
|
324
339
|
/** Oct JWK "k" (Key Value) Parameter */
|
|
325
340
|
k: string;
|
|
326
341
|
}
|
|
@@ -654,7 +669,12 @@ interface JWSVerifyResult<T extends JOSEPayload = JOSEPayload> {
|
|
|
654
669
|
}
|
|
655
670
|
/** Options for JWS verification */
|
|
656
671
|
interface JWSVerifyOptions extends JWTClaimValidationOptions {
|
|
657
|
-
/**
|
|
672
|
+
/**
|
|
673
|
+
* List of allowed algorithms. If provided, the JWS `alg` must be in this list.
|
|
674
|
+
* When omitted, the allowlist is inferred from the key's shape — keys without
|
|
675
|
+
* usable metadata (raw `Uint8Array`/string, alg-less JWKs, lookup functions)
|
|
676
|
+
* cannot be inferred and require this option explicitly.
|
|
677
|
+
*/
|
|
658
678
|
algorithms?: JWSAlgorithm[];
|
|
659
679
|
/** If true, forces the payload to be returned as a Uint8Array, otherwise type is inferred. */
|
|
660
680
|
forceUint8Array?: boolean;
|
|
@@ -949,7 +969,12 @@ interface JWEEncryptOptions {
|
|
|
949
969
|
* JWE (JSON Web Encryption) decryption options
|
|
950
970
|
*/
|
|
951
971
|
interface JWEDecryptOptions extends JWTClaimValidationOptions {
|
|
952
|
-
/**
|
|
972
|
+
/**
|
|
973
|
+
* A list of allowed JWE "alg" (Algorithm) Header Parameter values for key management.
|
|
974
|
+
* When omitted, the allowlist is inferred from the key's shape — password strings
|
|
975
|
+
* and raw `Uint8Array` keys infer the PBES2 family plus `dir`; lookup functions
|
|
976
|
+
* cannot be inferred and require this option explicitly.
|
|
977
|
+
*/
|
|
953
978
|
algorithms?: KeyManagementAlgorithm[];
|
|
954
979
|
/** A list of allowed JWE "enc" (Encryption Algorithm) Header Parameter values for content encryption. */
|
|
955
980
|
encryptionAlgorithms?: ContentEncryptionAlgorithm[];
|
|
@@ -1116,4 +1141,4 @@ type ExpiresIn = Duration;
|
|
|
1116
1141
|
type NotBeforeIn = Duration;
|
|
1117
1142
|
/** Duration for `maxTokenAge` validation on {@link verify} / {@link decrypt}. */
|
|
1118
1143
|
type MaxTokenAge = Duration;
|
|
1119
|
-
export {
|
|
1144
|
+
export { CompositeKey, ContentEncryptionAlgorithm, DeriveKeyOptions, DeriveKeyReturn, Duration, ExpiresIn, GenerateJWKOptions, GenerateJWKReturn, GenerateKeyAlgorithm, GenerateKeyOptions, GenerateKeyReturn, JOSEPayload, JWEAsymmetricPrivateJWK, JWEAsymmetricPublicJWK, JWEDecryptJWK, JWEDecryptOptions, JWEDecryptResult, JWEEncryptJWK, JWEEncryptOptions, JWEFlattenedSerialization, JWEGeneralRecipient, JWEGeneralSerialization, JWEHeaderParameters, JWEKeyManagementHeaderParameters, JWEMultiDecryptOptions, JWEMultiDecryptResult, JWEMultiEncryptOptions, JWEMultiRecipient, JWEProtectedHeader, JWK, JWKAlgorithm, JWKCacheAdapter, JWKLookupFunction, JWKLookupFunctionHeader, JWKPEMAlgorithm, JWKParameters, JWKSet, JWK_AES_CBC_HMAC, JWK_AES_GCM, JWK_AES_GCM_KW, JWK_AES_KW, JWK_Asymmetric, JWK_Asymmetric_Algorithm, JWK_EC, JWK_ECDH_ES, JWK_ECDSA, JWK_EC_Private, JWK_EC_Public, JWK_HMAC, JWK_OKP, JWK_OKP_Private, JWK_OKP_Public, JWK_OKP_SIGN, JWK_PBES2, JWK_Pair, JWK_Private, JWK_Public, JWK_RSA, JWK_RSA_ENC, JWK_RSA_PSS, JWK_RSA_Private, JWK_RSA_Public, JWK_RSA_SIGN, JWK_Symmetric, JWK_Symmetric_Algorithm, JWK_oct, JWSAlgorithm, JWSAsymmetricPrivateJWK, JWSAsymmetricPublicJWK, JWSFlattenedSerialization, JWSGeneralSerialization, JWSGeneralSignature, JWSHeaderParameters, JWSMultiSignOptions, JWSMultiSigner, JWSMultiVerifyAllOptions, JWSMultiVerifyOptions, JWSMultiVerifyOutcome, JWSMultiVerifyResult, JWSProtectedHeader, JWSSignJWK, JWSSignOptions, JWSVerifyJWK, JWSVerifyOptions, JWSVerifyResult, JWT, JWTClaimValidationOptions, JWTClaims, JWTError, JWTErrorCauseMap, JWTErrorCode, JoseHeaderParameters, KeyManagementAlgorithm, MaxTokenAge, NotBeforeIn, StrictOmit, UnwrapKeyOptions, UnwrappingKeyFor, WrapKeyOptions, WrapKeyResult, WrappingKeyFor, isJWTError };
|
package/dist/_chunks/jwe.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContentEncryptionAlgorithm, JOSEPayload, JWEDecryptJWK, JWEDecryptOptions, JWEDecryptResult, JWEEncryptJWK, JWEEncryptOptions, JWEFlattenedSerialization, JWEGeneralSerialization, JWEMultiDecryptOptions, JWEMultiDecryptResult, JWEMultiEncryptOptions, JWEMultiRecipient, JWKLookupFunction, JWKSet, KeyManagementAlgorithm } from "./index.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Encrypt a payload to multiple recipients using JWE General JSON Serialization
|
|
4
4
|
* (RFC 7516 §7.2.1).
|
|
@@ -81,4 +81,4 @@ declare function decrypt<T extends JOSEPayload>(jwe: string, key: CryptoKey | JW
|
|
|
81
81
|
declare function decrypt(jwe: string, key: CryptoKey | JWKSet | JWEDecryptJWK | string | Uint8Array<ArrayBuffer> | JWKLookupFunction, options: JWEDecryptOptions & {
|
|
82
82
|
forceUint8Array: true;
|
|
83
83
|
}): Promise<JWEDecryptResult<Uint8Array<ArrayBuffer>>>;
|
|
84
|
-
export {
|
|
84
|
+
export { decrypt, decryptMulti, encrypt, encryptMulti, generalToFlattened };
|
package/dist/_chunks/jwe.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { JWTError, applyTypCtyDefaults, computeJwtTimeClaims, decodePayloadFromBytes, getPlaintextBytes, isCryptoKey, isJWK, isJWKSet, validateCriticalHeadersJWE } from "./utils.mjs";
|
|
2
|
+
import { base64UrlDecode, base64UrlEncode, sanitizeObjectCopy, secureRandomBytes, textEncoder } from "./libs/unsecure.mjs";
|
|
3
|
+
import { decrypt as decrypt$1, encrypt as encrypt$1, encryptKey, generateCEK, generateIV, getJWKsFromSet, importKey, unwrapKey } from "./jwk.mjs";
|
|
4
|
+
import { JWE_ALG_CTX, buildJWKSetFilter, checkAlgAllowed, decodeProtectedHeader, parseEphemeralKey, validateJwtClaimsIfJsonPayload } from "./_internal.mjs";
|
|
5
5
|
const DIRECT_ALGS = /* @__PURE__ */ new Set(["dir", "ECDH-ES"]);
|
|
6
6
|
async function encryptMulti(payload, recipients, options = {}) {
|
|
7
7
|
if (!Array.isArray(recipients) || recipients.length === 0) throw new JWTError("encryptMulti requires at least one recipient.", "ERR_JWE_INVALID");
|
|
@@ -404,4 +404,4 @@ function _buildJWEHeader(alg, enc, key, userHeader, keyManagementParams, payload
|
|
|
404
404
|
header.enc = enc;
|
|
405
405
|
return applyTypCtyDefaults(header, payload);
|
|
406
406
|
}
|
|
407
|
-
export {
|
|
407
|
+
export { decrypt, decryptMulti, encrypt, encryptMulti, generalToFlattened };
|
package/dist/_chunks/jwk.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { JWTError, assertCryptoKey, concatUint8Arrays, isAsymmetricJWK, isCryptoKey, isCryptoKeyPair, isJWK, isJWKSet } from "./utils.mjs";
|
|
2
|
+
import { base64Decode, base64Encode, base64UrlDecode, base64UrlEncode, sanitizeObjectCopy, secureRandomBytes, textEncoder } from "./libs/unsecure.mjs";
|
|
3
3
|
async function sign(alg, key, data) {
|
|
4
4
|
checkSigCryptoKey(key, alg, "sign");
|
|
5
5
|
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, key.algorithm), key, data);
|
|
@@ -110,20 +110,20 @@ function checkUsage$4(key, usage) {
|
|
|
110
110
|
if (usage && !key.usages.includes(usage)) throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
111
111
|
}
|
|
112
112
|
const IV_BIT_LENGTHS = {
|
|
113
|
-
A128GCM: 96,
|
|
114
|
-
A128GCMKW: 96,
|
|
115
|
-
A192GCM: 96,
|
|
116
|
-
A192GCMKW: 96,
|
|
117
|
-
A256GCM: 96,
|
|
118
|
-
A256GCMKW: 96,
|
|
113
|
+
"A128GCM": 96,
|
|
114
|
+
"A128GCMKW": 96,
|
|
115
|
+
"A192GCM": 96,
|
|
116
|
+
"A192GCMKW": 96,
|
|
117
|
+
"A256GCM": 96,
|
|
118
|
+
"A256GCMKW": 96,
|
|
119
119
|
"A128CBC-HS256": 128,
|
|
120
120
|
"A192CBC-HS384": 128,
|
|
121
121
|
"A256CBC-HS512": 128
|
|
122
122
|
};
|
|
123
123
|
const CEK_BIT_LENGTHS = {
|
|
124
|
-
A128GCM: 128,
|
|
125
|
-
A192GCM: 192,
|
|
126
|
-
A256GCM: 256,
|
|
124
|
+
"A128GCM": 128,
|
|
125
|
+
"A192GCM": 192,
|
|
126
|
+
"A256GCM": 256,
|
|
127
127
|
"A128CBC-HS256": 256,
|
|
128
128
|
"A192CBC-HS384": 384,
|
|
129
129
|
"A256CBC-HS512": 512
|
|
@@ -151,6 +151,16 @@ function checkCEKLength(cek, expected) {
|
|
|
151
151
|
const actual = cek.byteLength << 3;
|
|
152
152
|
if (actual !== expected) throw new Error(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`);
|
|
153
153
|
}
|
|
154
|
+
function assertOctKeyLength(bytes, alg) {
|
|
155
|
+
if (!alg) return;
|
|
156
|
+
if (alg === "HS256" || alg === "HS384" || alg === "HS512") {
|
|
157
|
+
const minBytes = Number.parseInt(alg.slice(2), 10) >> 3;
|
|
158
|
+
if (bytes.length < minBytes) throw new JWTError(`${alg} requires a key of at least ${minBytes} bytes (got ${bytes.length})`, "ERR_JWK_INVALID");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const exactBits = /^A(128|192|256)(GCM)?KW$/.test(alg) ? Number.parseInt(alg.slice(1, 4), 10) : CEK_BIT_LENGTHS[alg];
|
|
162
|
+
if (exactBits !== void 0 && bytes.length << 3 !== exactBits) throw new JWTError(`${alg} requires a key of exactly ${exactBits >> 3} bytes (got ${bytes.length})`, "ERR_JWK_INVALID");
|
|
163
|
+
}
|
|
154
164
|
function checkAESCryptoKey(key, alg, usage) {
|
|
155
165
|
switch (alg) {
|
|
156
166
|
case "A128GCM":
|
|
@@ -192,7 +202,7 @@ async function aesKwUnwrap(alg, key, encryptedKey) {
|
|
|
192
202
|
return new Uint8Array(await crypto.subtle.exportKey("raw", cryptoKeyCek));
|
|
193
203
|
}
|
|
194
204
|
async function gcmkwEncrypt(alg, key, plaintext, iv) {
|
|
195
|
-
const wrapped = await encrypt(alg.slice(0, 7), plaintext, key, iv, new Uint8Array(0));
|
|
205
|
+
const wrapped = await encrypt(alg.slice(0, 7), plaintext, key, iv, /* @__PURE__ */ new Uint8Array(0));
|
|
196
206
|
return {
|
|
197
207
|
encryptedKey: wrapped.ciphertext,
|
|
198
208
|
iv: base64UrlEncode(wrapped.iv),
|
|
@@ -200,7 +210,7 @@ async function gcmkwEncrypt(alg, key, plaintext, iv) {
|
|
|
200
210
|
};
|
|
201
211
|
}
|
|
202
212
|
async function gcmkwDecrypt(alg, key, ciphertext, iv, tag) {
|
|
203
|
-
return decrypt(alg.slice(0, 7), key, ciphertext, iv, tag, new Uint8Array(0));
|
|
213
|
+
return decrypt(alg.slice(0, 7), key, ciphertext, iv, tag, /* @__PURE__ */ new Uint8Array(0));
|
|
204
214
|
}
|
|
205
215
|
async function encrypt(enc, plaintext, cek, iv, aad) {
|
|
206
216
|
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) throw new TypeError("Key must be one of type: CryptoKey or Uint8Array");
|
|
@@ -379,7 +389,7 @@ function writeUInt32BE$1(buf, value, offset) {
|
|
|
379
389
|
function uint64be(value) {
|
|
380
390
|
const high = Math.floor(value / 2 ** 32);
|
|
381
391
|
const low = value % 2 ** 32;
|
|
382
|
-
const buf = new Uint8Array(8);
|
|
392
|
+
const buf = /* @__PURE__ */ new Uint8Array(8);
|
|
383
393
|
writeUInt32BE$1(buf, high, 0);
|
|
384
394
|
writeUInt32BE$1(buf, low, 4);
|
|
385
395
|
return buf;
|
|
@@ -529,7 +539,7 @@ function getHashLength(hash) {
|
|
|
529
539
|
function checkUsage$2(key, usage) {
|
|
530
540
|
if (usage && !key.usages.includes(usage)) throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
531
541
|
}
|
|
532
|
-
async function deriveECDHESKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) {
|
|
542
|
+
async function deriveECDHESKey(publicKey, privateKey, algorithm, keyLength, apu = /* @__PURE__ */ new Uint8Array(0), apv = /* @__PURE__ */ new Uint8Array(0)) {
|
|
533
543
|
checkECDHCryptoKey(publicKey, "ECDH");
|
|
534
544
|
checkECDHCryptoKey(privateKey, "ECDH", "deriveBits");
|
|
535
545
|
const value = concatUint8Arrays(lengthAndInput(textEncoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
|
|
@@ -589,7 +599,7 @@ function writeUInt32BE(buf, value, offset) {
|
|
|
589
599
|
], offset);
|
|
590
600
|
}
|
|
591
601
|
function uint32be(value) {
|
|
592
|
-
const buf = new Uint8Array(4);
|
|
602
|
+
const buf = /* @__PURE__ */ new Uint8Array(4);
|
|
593
603
|
writeUInt32BE(buf, value, 0);
|
|
594
604
|
return buf;
|
|
595
605
|
}
|
|
@@ -642,7 +652,7 @@ async function getPBKDF2CryptoKey(key, alg, options = {}) {
|
|
|
642
652
|
checkPBES2CryptoKey(key, alg, usage);
|
|
643
653
|
return key;
|
|
644
654
|
}
|
|
645
|
-
const PUBLIC_EPK_FIELDS = new Set([
|
|
655
|
+
const PUBLIC_EPK_FIELDS = /* @__PURE__ */ new Set([
|
|
646
656
|
"kty",
|
|
647
657
|
"crv",
|
|
648
658
|
"x",
|
|
@@ -813,7 +823,7 @@ const assertPEMLabel = (pem, descriptor) => {
|
|
|
813
823
|
}
|
|
814
824
|
};
|
|
815
825
|
const genericExport = async (keyType, keyFormat, key) => {
|
|
816
|
-
if (!isCryptoKey(key)) throw new TypeError(`Key must be
|
|
826
|
+
if (!isCryptoKey(key)) throw new TypeError(`Key must be of type CryptoKey, got ${typeof key}`);
|
|
817
827
|
if (!key.extractable) throw new TypeError("CryptoKey is not extractable");
|
|
818
828
|
if (key.type !== keyType) throw new TypeError(`key is not a ${keyType} key`);
|
|
819
829
|
return formatPEM(base64Encode(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`);
|
|
@@ -1007,11 +1017,12 @@ const getSPKI = (x509) => {
|
|
|
1007
1017
|
type: "spki"
|
|
1008
1018
|
});
|
|
1009
1019
|
} catch {}
|
|
1010
|
-
|
|
1020
|
+
const raw = base64Decode(x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ""), { returnAs: "uint8array" });
|
|
1021
|
+
return formatPEM(spkiFromX509(raw), "PUBLIC KEY");
|
|
1011
1022
|
};
|
|
1012
1023
|
async function generateKey(alg, options = {}) {
|
|
1013
1024
|
const exportToJWK = options.toJWK !== void 0 && options.toJWK !== false;
|
|
1014
|
-
const defaultExtractable = options.extractable !== false;
|
|
1025
|
+
const defaultExtractable = exportToJWK || options.extractable !== false;
|
|
1015
1026
|
if (alg === "A128CBC-HS256" || alg === "A192CBC-HS384" || alg === "A256CBC-HS512") {
|
|
1016
1027
|
const keyBytes = secureRandomBytes(bitLengthCEK(alg) >> 3);
|
|
1017
1028
|
if (exportToJWK) return keyToJWK(keyBytes);
|
|
@@ -1039,7 +1050,7 @@ async function generateKey(alg, options = {}) {
|
|
|
1039
1050
|
return key;
|
|
1040
1051
|
}
|
|
1041
1052
|
async function generateJWK(alg, options) {
|
|
1042
|
-
const { keyUsage,
|
|
1053
|
+
const { keyUsage, modulusLength, publicExponent, namedCurve, ...jwkParams } = options ?? {};
|
|
1043
1054
|
const kid = typeof jwkParams.kid === "string" ? jwkParams.kid : crypto.randomUUID();
|
|
1044
1055
|
const extraParams = {
|
|
1045
1056
|
...jwkParams,
|
|
@@ -1047,7 +1058,6 @@ async function generateJWK(alg, options) {
|
|
|
1047
1058
|
};
|
|
1048
1059
|
const result = await generateKey(alg, {
|
|
1049
1060
|
keyUsage,
|
|
1050
|
-
extractable,
|
|
1051
1061
|
modulusLength,
|
|
1052
1062
|
publicExponent,
|
|
1053
1063
|
namedCurve,
|
|
@@ -1089,12 +1099,11 @@ async function deriveKeyFromPassword(password, alg, options) {
|
|
|
1089
1099
|
return derivedKey;
|
|
1090
1100
|
}
|
|
1091
1101
|
async function deriveJWKFromPassword(password, alg, options) {
|
|
1092
|
-
const { salt, iterations, keyUsage,
|
|
1102
|
+
const { salt, iterations, keyUsage, ...jwkParams } = options;
|
|
1093
1103
|
const result = await deriveKeyFromPassword(password, alg, {
|
|
1094
1104
|
salt,
|
|
1095
1105
|
iterations,
|
|
1096
1106
|
keyUsage,
|
|
1097
|
-
extractable,
|
|
1098
1107
|
toJWK: true
|
|
1099
1108
|
});
|
|
1100
1109
|
return Object.keys(jwkParams).length > 0 ? {
|
|
@@ -1131,9 +1140,16 @@ async function importKey(key, algOrOptions) {
|
|
|
1131
1140
|
}
|
|
1132
1141
|
if (isJWK(key)) if ("k" in key && typeof key.k === "string") {
|
|
1133
1142
|
const rawBytes = base64UrlDecode(key.k, { returnAs: "uint8array" });
|
|
1143
|
+
assertOctKeyLength(rawBytes, key.alg || alg);
|
|
1134
1144
|
if (typeof algOrOptions === "object" && algOrOptions.asCryptoKey) {
|
|
1135
1145
|
const { algorithm, usage, extractable = false } = algOrOptions;
|
|
1136
1146
|
if (!algorithm || !usage) throw new JWTError("asCryptoKey option requires `algorithm` and `usage` to be provided.", "ERR_JWK_INVALID");
|
|
1147
|
+
if (typeof algorithm === "object" && algorithm.name === "HMAC") {
|
|
1148
|
+
const hash = algorithm.hash;
|
|
1149
|
+
const hashName = typeof hash === "string" ? hash : hash?.name;
|
|
1150
|
+
const minBytes = Number.parseInt(hashName?.slice(-3) ?? "", 10) / 8;
|
|
1151
|
+
if (minBytes && rawBytes.length < minBytes) throw new JWTError(`HMAC with ${hashName} requires a key of at least ${minBytes} bytes (got ${rawBytes.length})`, "ERR_JWK_INVALID");
|
|
1152
|
+
}
|
|
1137
1153
|
return crypto.subtle.importKey("raw", rawBytes, algorithm, extractable, usage);
|
|
1138
1154
|
}
|
|
1139
1155
|
return rawBytes;
|
|
@@ -1186,7 +1202,7 @@ async function wrapKey(alg, keyToWrap, wrappingKey, options = {}) {
|
|
|
1186
1202
|
const cekBytes = keyToWrap instanceof Uint8Array ? keyToWrap : new Uint8Array(await crypto.subtle.exportKey("raw", keyToWrap));
|
|
1187
1203
|
const importedWrappingKey = await resolveWrappingKey(alg, wrappingKey, "public");
|
|
1188
1204
|
switch (alg) {
|
|
1189
|
-
case "dir": return { encryptedKey: new Uint8Array(0) };
|
|
1205
|
+
case "dir": return { encryptedKey: /* @__PURE__ */ new Uint8Array(0) };
|
|
1190
1206
|
case "A128KW":
|
|
1191
1207
|
case "A192KW":
|
|
1192
1208
|
case "A256KW": return { encryptedKey: await aesKwWrap(alg, importedWrappingKey, cekBytes) };
|
|
@@ -1217,8 +1233,8 @@ async function wrapKey(alg, keyToWrap, wrappingKey, options = {}) {
|
|
|
1217
1233
|
case "ECDH-ES+A256KW": {
|
|
1218
1234
|
if (!(importedWrappingKey instanceof CryptoKey)) throw new TypeError("ECDH-ES requires the wrapping key to be a CryptoKey (recipient's public key)");
|
|
1219
1235
|
if (!isECDHKeyAllowed(importedWrappingKey)) throw new JWTError("ECDH with the provided key is not allowed or not supported", "ERR_JWK_INVALID");
|
|
1220
|
-
const apu = options.ecdh?.partyUInfo ?? new Uint8Array(0);
|
|
1221
|
-
const apv = options.ecdh?.partyVInfo ?? new Uint8Array(0);
|
|
1236
|
+
const apu = options.ecdh?.partyUInfo ?? /* @__PURE__ */ new Uint8Array(0);
|
|
1237
|
+
const apv = options.ecdh?.partyVInfo ?? /* @__PURE__ */ new Uint8Array(0);
|
|
1222
1238
|
const { ephemeralPrivateKey, epkJwk } = await resolveECDHEphemeralPair(importedWrappingKey, options.ecdh?.ephemeralKey);
|
|
1223
1239
|
const infoAlg = alg === "ECDH-ES" ? (() => {
|
|
1224
1240
|
if (!options.ecdh?.enc) throw new JWTError("ECDH-ES direct key agreement requires options.ecdh.enc (the target content encryption algorithm)", "ERR_JWK_INVALID");
|
|
@@ -1226,7 +1242,7 @@ async function wrapKey(alg, keyToWrap, wrappingKey, options = {}) {
|
|
|
1226
1242
|
})() : alg;
|
|
1227
1243
|
const sharedSecret = await deriveECDHESKey(importedWrappingKey, ephemeralPrivateKey, infoAlg, alg === "ECDH-ES" ? bitLengthCEK(infoAlg) : Number.parseInt(alg.slice(-5, -2), 10), apu, apv);
|
|
1228
1244
|
const wrapResult = {
|
|
1229
|
-
encryptedKey: new Uint8Array(0),
|
|
1245
|
+
encryptedKey: /* @__PURE__ */ new Uint8Array(0),
|
|
1230
1246
|
epk: epkJwk
|
|
1231
1247
|
};
|
|
1232
1248
|
if (apu.length > 0) wrapResult.apu = base64UrlEncode(apu);
|
|
@@ -1291,8 +1307,8 @@ async function unwrapKey(alg, wrappedKey, unwrappingKey, options = {}) {
|
|
|
1291
1307
|
if (!isECDHKeyAllowed(importedUnwrappingKey)) throw new JWTError("ECDH with the provided key is not allowed or not supported", "ERR_JWK_INVALID");
|
|
1292
1308
|
const epkCandidate = options.epk instanceof CryptoKey ? options.epk : await normalizeKey(options.epk, alg);
|
|
1293
1309
|
if (!(epkCandidate instanceof CryptoKey)) throw new JWTError("Failed to normalize ECDH ephemeral public key", "ERR_JWK_INVALID");
|
|
1294
|
-
const apuBytes = typeof options.apu === "string" ? base64UrlDecode(options.apu, { returnAs: "uint8array" }) : options.apu ?? new Uint8Array(0);
|
|
1295
|
-
const apvBytes = typeof options.apv === "string" ? base64UrlDecode(options.apv, { returnAs: "uint8array" }) : options.apv ?? new Uint8Array(0);
|
|
1310
|
+
const apuBytes = typeof options.apu === "string" ? base64UrlDecode(options.apu, { returnAs: "uint8array" }) : options.apu ?? /* @__PURE__ */ new Uint8Array(0);
|
|
1311
|
+
const apvBytes = typeof options.apv === "string" ? base64UrlDecode(options.apv, { returnAs: "uint8array" }) : options.apv ?? /* @__PURE__ */ new Uint8Array(0);
|
|
1296
1312
|
const infoAlg = alg === "ECDH-ES" ? options.enc : alg;
|
|
1297
1313
|
if (!infoAlg) throw new JWTError("ECDH-ES requires content encryption algorithm ('enc') to derive the shared secret", "ERR_JWE_INVALID");
|
|
1298
1314
|
const sharedSecret = await deriveECDHESKey(epkCandidate, importedUnwrappingKey, infoAlg, alg === "ECDH-ES" ? bitLengthCEK(infoAlg) : Number.parseInt(alg.slice(-5, -2), 10), apuBytes, apvBytes);
|
|
@@ -1310,7 +1326,7 @@ async function unwrapKey(alg, wrappedKey, unwrappingKey, options = {}) {
|
|
|
1310
1326
|
return await crypto.subtle.importKey("raw", unwrappedCekBytes, options.unwrappedKeyAlgorithm || { name: "AES-GCM" }, defaultExtractable, options.keyUsage || ["encrypt", "decrypt"]);
|
|
1311
1327
|
}
|
|
1312
1328
|
async function importPEM(pem, alg, options) {
|
|
1313
|
-
const extractable =
|
|
1329
|
+
const extractable = true;
|
|
1314
1330
|
const pemType = options?.pemType ?? inferPEMType(pem);
|
|
1315
1331
|
if (!pemType) throw new JWTError("Cannot infer PEM type from the input; pass \"options.pemType\" explicitly.", "ERR_JWK_INVALID");
|
|
1316
1332
|
let cryptoKey;
|
|
@@ -1324,7 +1340,7 @@ async function importPEM(pem, alg, options) {
|
|
|
1324
1340
|
case "x509":
|
|
1325
1341
|
cryptoKey = await fromX509(pem, alg, { extractable });
|
|
1326
1342
|
break;
|
|
1327
|
-
default: throw new JWTError(`Unsupported PEM type: ${pemType}`, "ERR_JWK_UNSUPPORTED");
|
|
1343
|
+
default: throw new JWTError(`Unsupported PEM type: ${String(pemType)}`, "ERR_JWK_UNSUPPORTED");
|
|
1328
1344
|
}
|
|
1329
1345
|
return {
|
|
1330
1346
|
...await exportKey(cryptoKey, options?.jwkParams),
|
|
@@ -1358,7 +1374,7 @@ async function exportPEM(jwk, options) {
|
|
|
1358
1374
|
case "spki":
|
|
1359
1375
|
if (cryptoKey.type !== "public") throw new JWTError(`Only 'public' type CryptoKeys can be exported to SPKI PEM format. Key type is '${cryptoKey.type}'.`, "ERR_JWK_INVALID");
|
|
1360
1376
|
return toSPKI(cryptoKey);
|
|
1361
|
-
default: throw new JWTError(`Unsupported PEM format: ${pemFormat}`, "ERR_JWK_UNSUPPORTED");
|
|
1377
|
+
default: throw new JWTError(`Unsupported PEM format: ${String(pemFormat)}`, "ERR_JWK_UNSUPPORTED");
|
|
1362
1378
|
}
|
|
1363
1379
|
}
|
|
1364
1380
|
async function exportToPEM(jwk, pemFormat, algForCryptoKeyImport) {
|
|
@@ -1386,7 +1402,7 @@ async function deriveSharedSecret(publicKey, privateKey, alg, options) {
|
|
|
1386
1402
|
else if (alg === "ECDH-ES") throw new JWTError("deriveSharedSecret with alg \"ECDH-ES\" requires an explicit keyLength in options", "ERR_JWK_INVALID");
|
|
1387
1403
|
else if (alg.startsWith("ECDH-ES+")) keyLength = Number.parseInt(alg.slice(-5, -2), 10);
|
|
1388
1404
|
else keyLength = bitLengthCEK(alg);
|
|
1389
|
-
return deriveECDHESKey(pubCryptoKey, privCryptoKey, alg, keyLength, options?.partyUInfo ?? new Uint8Array(0), options?.partyVInfo ?? new Uint8Array(0));
|
|
1405
|
+
return deriveECDHESKey(pubCryptoKey, privCryptoKey, alg, keyLength, options?.partyUInfo ?? /* @__PURE__ */ new Uint8Array(0), options?.partyVInfo ?? /* @__PURE__ */ new Uint8Array(0));
|
|
1390
1406
|
}
|
|
1391
1407
|
function getJWKFromSet(jwkSet, kidOrProtectedHeader) {
|
|
1392
1408
|
if (!jwkSet || !isJWKSet(jwkSet)) throw new JWTError("Invalid JWK Set provided", "ERR_JWK_INVALID");
|
|
@@ -1622,4 +1638,4 @@ function inferAesImportAlgorithm(enc, cekLengthBytes) {
|
|
|
1622
1638
|
length: bitLength
|
|
1623
1639
|
};
|
|
1624
1640
|
}
|
|
1625
|
-
export {
|
|
1641
|
+
export { WeakMapJWKCache, assertOctKeyLength, clearJWKCache, configureJWKCache, decrypt, deriveJWKFromPassword, deriveKeyFromPassword, deriveSharedSecret, encrypt, encryptKey, exportKey, exportPEM, exportToPEM, generateCEK, generateIV, generateJWK, generateKey, getJWKFromSet, getJWKsFromSet, importFromPEM, importKey, importPEM, sign, unwrapKey, verify, wrapKey };
|
package/dist/_chunks/jws.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JOSEPayload, JWKLookupFunction, JWKSet, JWSAlgorithm, JWSFlattenedSerialization, JWSGeneralSerialization, JWSMultiSignOptions, JWSMultiSigner, JWSMultiVerifyAllOptions, JWSMultiVerifyOptions, JWSMultiVerifyOutcome, JWSMultiVerifyResult, JWSSignJWK, JWSSignOptions, JWSVerifyJWK, JWSVerifyOptions, JWSVerifyResult } from "./index.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Sign a payload with multiple signers using JWS General JSON Serialization
|
|
4
4
|
* (RFC 7515 §7.2.1).
|
|
@@ -108,4 +108,4 @@ declare function verify<T extends JOSEPayload>(jws: string, key: CryptoKey | JWK
|
|
|
108
108
|
declare function verify(jws: string, key: CryptoKey | JWKSet | JWSVerifyJWK | Uint8Array<ArrayBuffer> | JWKLookupFunction, options: JWSVerifyOptions & {
|
|
109
109
|
forceUint8Array: true;
|
|
110
110
|
}): Promise<JWSVerifyResult<Uint8Array<ArrayBuffer>>>;
|
|
111
|
-
export {
|
|
111
|
+
export { generalToFlattenedJWS, sign, signMulti, verify, verifyMulti, verifyMultiAll };
|
package/dist/_chunks/jws.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { JWTError, applyTypCtyDefaults, computeJwtTimeClaims, getPlaintextBytes, isJWK, isJWKSet, validateCriticalHeadersJWS } from "./utils.mjs";
|
|
2
|
+
import { base64UrlDecode, base64UrlEncode, sanitizeObjectCopy, textDecoder, textEncoder } from "./libs/unsecure.mjs";
|
|
3
|
+
import { getJWKsFromSet, importKey, sign as sign$1, verify as verify$1 } from "./jwk.mjs";
|
|
4
|
+
import { JWS_ALG_CTX, buildJWKSetFilter, checkAlgAllowed, decodeJWSPayload, decodeProtectedHeader, resolveSigningKey, validateJwtClaimsIfJsonPayload } from "./_internal.mjs";
|
|
5
5
|
async function signMulti(payload, signers, options = {}) {
|
|
6
6
|
if (!Array.isArray(signers) || signers.length === 0) throw new JWTError("signMulti requires at least one signer.", "ERR_JWS_INVALID");
|
|
7
7
|
const resolvedAlgs = signers.map((s, i) => _resolveSignerAlg(s.key, i));
|
|
@@ -327,7 +327,7 @@ async function verify(jws, key, options = {}) {
|
|
|
327
327
|
try {
|
|
328
328
|
payload = decodeJWSPayload(payloadEncoded, useB64, options.forceUint8Array);
|
|
329
329
|
} catch (error_) {
|
|
330
|
-
throw new JWTError(`Invalid JWS: Payload decoding failed (${error_ instanceof Error ? error_.message : error_})`, "ERR_JWS_INVALID");
|
|
330
|
+
throw new JWTError(`Invalid JWS: Payload decoding failed (${error_ instanceof Error ? error_.message : String(error_)})`, "ERR_JWS_INVALID");
|
|
331
331
|
}
|
|
332
332
|
validateCriticalHeadersJWS(protectedHeader, options.recognizedHeaders);
|
|
333
333
|
validateJwtClaimsIfJsonPayload(payload, options);
|
|
@@ -346,4 +346,4 @@ function _buildJWSHeader(alg, key, userHeader, payload) {
|
|
|
346
346
|
if (header.b64 === true) delete header.b64;
|
|
347
347
|
return header;
|
|
348
348
|
}
|
|
349
|
-
export {
|
|
349
|
+
export { generalToFlattenedJWS, sign, signMulti, verify, verifyMulti, verifyMultiAll };
|
|
@@ -91,4 +91,4 @@ declare function base64UrlDecode(data: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
|
91
91
|
type DecodeReturnAs = "string" | "uint8array" | "bytes";
|
|
92
92
|
declare const textEncoder: TextEncoder;
|
|
93
93
|
declare const textDecoder: TextDecoder;
|
|
94
|
-
export {
|
|
94
|
+
export { base64Decode, base64Encode, base64UrlDecode, base64UrlEncode, safeJsonParse, sanitizeObject, sanitizeObjectCopy, secureRandomBytes, textDecoder, textEncoder };
|
|
@@ -106,7 +106,7 @@ function base64Decode(data, options) {
|
|
|
106
106
|
const isBufferInput = data instanceof Uint8Array;
|
|
107
107
|
const str = isBufferInput ? textDecoder.decode(data) : data;
|
|
108
108
|
const decodeToString = (options?.returnAs ?? (isBufferInput ? "uint8array" : "string")) === "string";
|
|
109
|
-
if (!str) return decodeToString ? "" : new Uint8Array(0);
|
|
109
|
+
if (!str) return decodeToString ? "" : /* @__PURE__ */ new Uint8Array(0);
|
|
110
110
|
if (_hasBuffer) {
|
|
111
111
|
const buf = _Buffer.from(str, "base64");
|
|
112
112
|
return decodeToString ? buf.toString("utf8") : new Uint8Array(buf);
|
|
@@ -119,7 +119,7 @@ function base64UrlDecode(data, options) {
|
|
|
119
119
|
const isBufferInput = data instanceof Uint8Array;
|
|
120
120
|
let str = isBufferInput ? textDecoder.decode(data) : data;
|
|
121
121
|
const decodeToString = (options?.returnAs ?? (isBufferInput ? "uint8array" : "string")) === "string";
|
|
122
|
-
if (!str) return decodeToString ? "" : new Uint8Array(0);
|
|
122
|
+
if (!str) return decodeToString ? "" : /* @__PURE__ */ new Uint8Array(0);
|
|
123
123
|
if (_hasBuffer) {
|
|
124
124
|
const buf = _Buffer.from(str, "base64url");
|
|
125
125
|
return decodeToString ? buf.toString("utf8") : new Uint8Array(buf);
|
|
@@ -146,4 +146,4 @@ function secureRandomBytes(length) {
|
|
|
146
146
|
}
|
|
147
147
|
return bytes;
|
|
148
148
|
}
|
|
149
|
-
export {
|
|
149
|
+
export { base64Decode, base64Encode, base64UrlDecode, base64UrlEncode, safeJsonParse, sanitizeObject, sanitizeObjectCopy, secureRandomBytes, textDecoder, textEncoder };
|
package/dist/_chunks/utils.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { base64UrlDecode, safeJsonParse, textDecoder, textEncoder } from "./libs/unsecure.mjs";
|
|
2
2
|
var JWTError = class extends Error {
|
|
3
3
|
code;
|
|
4
4
|
cause;
|
|
@@ -209,7 +209,9 @@ function _parseDurationSeconds(value) {
|
|
|
209
209
|
if (typeof value === "string") {
|
|
210
210
|
const match = value.match(DURATION_REGEX);
|
|
211
211
|
if (!match || !match[1]) throw new TypeError("Invalid duration format. Must be an integer or a string like '10m', '2h', '7D', etc.");
|
|
212
|
-
|
|
212
|
+
const n = Number.parseInt(match[1], 10);
|
|
213
|
+
const unit = match[2] || "s";
|
|
214
|
+
return n * TIME_CONSTANTS[unit];
|
|
213
215
|
}
|
|
214
216
|
throw new TypeError("Duration must be a number or a string representing time.");
|
|
215
217
|
}
|
|
@@ -317,7 +319,7 @@ const BASE_PROCESSED_JWE = [
|
|
|
317
319
|
function validateCriticalHeadersJWS(protectedHeader, recognizedHeaders = []) {
|
|
318
320
|
if (!protectedHeader.crit) return;
|
|
319
321
|
const missingHeaderParams = /* @__PURE__ */ new Set();
|
|
320
|
-
const recognizedParams = new Set([...recognizedHeaders, ...BASE_PROCESSED_JWS]);
|
|
322
|
+
const recognizedParams = /* @__PURE__ */ new Set([...recognizedHeaders, ...BASE_PROCESSED_JWS]);
|
|
321
323
|
for (const param of protectedHeader.crit) {
|
|
322
324
|
if (recognizedParams.has(param) && (param in protectedHeader || param === "b64")) continue;
|
|
323
325
|
missingHeaderParams.add(param);
|
|
@@ -326,7 +328,7 @@ function validateCriticalHeadersJWS(protectedHeader, recognizedHeaders = []) {
|
|
|
326
328
|
}
|
|
327
329
|
function validateCriticalHeadersJWE(protectedHeader, recognizedHeaders) {
|
|
328
330
|
if (!protectedHeader.crit) return;
|
|
329
|
-
const understoodParams = new Set([...recognizedHeaders || [], ...BASE_PROCESSED_JWE]);
|
|
331
|
+
const understoodParams = /* @__PURE__ */ new Set([...recognizedHeaders || [], ...BASE_PROCESSED_JWE]);
|
|
330
332
|
for (const critParam of protectedHeader.crit) {
|
|
331
333
|
if (!Object.prototype.hasOwnProperty.call(protectedHeader, critParam)) throw new JWTError(`Critical header parameter "${critParam}" listed in "crit" but not present in the protected header.`, "ERR_JWE_INVALID");
|
|
332
334
|
if (!understoodParams.has(critParam)) throw new JWTError(`Unprocessed critical header parameters: ${critParam}`, "ERR_JWE_INVALID");
|
|
@@ -346,7 +348,7 @@ function maybeArray(item) {
|
|
|
346
348
|
return Array.isArray(item) ? item : [item];
|
|
347
349
|
}
|
|
348
350
|
function isJWK(key) {
|
|
349
|
-
return typeof key === "object" && key !== null && "kty"
|
|
351
|
+
return typeof key === "object" && key !== null && (key.kty === "oct" || key.kty === "RSA" || key.kty === "EC" || key.kty === "OKP");
|
|
350
352
|
}
|
|
351
353
|
function isJWKSet(key) {
|
|
352
354
|
return key && typeof key === "object" && "keys" in key && Array.isArray(key.keys);
|
|
@@ -387,4 +389,4 @@ function isPublicJWK(key) {
|
|
|
387
389
|
}
|
|
388
390
|
return false;
|
|
389
391
|
}
|
|
390
|
-
export {
|
|
392
|
+
export { JWTError, applyTypCtyDefaults, assertCryptoKey, computeDurationInSeconds, computeExpiresInSeconds, computeJwtTimeClaims, computeMaxTokenAgeSeconds, concatUint8Arrays, decodeMaybeJWTString, decodePayloadFromB64UrlSegment, decodePayloadFromBytes, getPlaintextBytes, inferJWEAllowedAlgorithms, inferJWSAllowedAlgorithms, isAsymmetricJWK, isCryptoKey, isCryptoKeyPair, isJWK, isJWKSet, isJWTContent, isJWTError, isPrivateJWK, isPublicJWK, isSymmetricJWK, maybeArray, validateCriticalHeadersJWE, validateCriticalHeadersJWS, validateJwtClaims };
|