jose 6.0.5 → 6.0.7

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.
@@ -94,6 +94,7 @@ import type * as types from '../types.d.ts';
94
94
  * ```
95
95
  */
96
96
  export declare const customFetch: unique symbol;
97
+ /** See {@link customFetch}. */
97
98
  export type FetchImplementation = (url: string, options: {
98
99
  headers: Headers;
99
100
  method: 'GET';
@@ -175,10 +176,12 @@ export interface RemoteJWKSetOptions {
175
176
  /** See {@link customFetch}. */
176
177
  [customFetch]?: FetchImplementation;
177
178
  }
179
+ /** See {@link jwksCache}. */
178
180
  export interface ExportedJWKSCache {
179
181
  jwks: types.JSONWebKeySet;
180
182
  uat: number;
181
183
  }
184
+ /** See {@link jwksCache}. */
182
185
  export type JWKSCacheInput = ExportedJWKSCache | Record<string, never>;
183
186
  /**
184
187
  * Returns a function that resolves a JWS JOSE Header to a public key object downloaded from a
@@ -6,7 +6,12 @@
6
6
  import type * as types from '../types.d.ts';
7
7
  /** Secret generation function options. */
8
8
  export interface GenerateSecretOptions {
9
- /** The value to use as {@link !SubtleCrypto.generateKey} `extractable` argument. Default is false. */
9
+ /**
10
+ * The value to use as {@link !SubtleCrypto.generateKey} `extractable` argument. Default is false.
11
+ *
12
+ * Note: Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
13
+ * {@link !CryptoKey} this option has no effect for them.
14
+ */
10
15
  extractable?: boolean;
11
16
  }
12
17
  /**
@@ -14,6 +19,9 @@ export interface GenerateSecretOptions {
14
19
  *
15
20
  * Note: The secret key is generated with `extractable` set to `false` by default.
16
21
  *
22
+ * Note: Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as
23
+ * {@link !CryptoKey} this method yields a {@link !Uint8Array} for them instead.
24
+ *
17
25
  * This function is exported (as a named export) from the main `'jose'` module entry point as well
18
26
  * as from its subpath export `'jose/generate/secret'`.
19
27
  *
@@ -8,7 +8,7 @@ import type * as types from '../types.d.ts';
8
8
  export interface KeyImportOptions {
9
9
  /**
10
10
  * The value to use as {@link !SubtleCrypto.importKey} `extractable` argument. Default is false for
11
- * private and secret keys, true otherwise.
11
+ * private keys, true otherwise.
12
12
  */
13
13
  extractable?: boolean;
14
14
  }
@@ -59,11 +59,14 @@ export declare function importX509(x509: string, alg: string, options?: KeyImpor
59
59
  export declare function importPKCS8(pkcs8: string, alg: string, options?: KeyImportOptions): Promise<types.CryptoKey>;
60
60
  /**
61
61
  * Imports a JWK to a {@link !CryptoKey}. Either the JWK "alg" (Algorithm) Parameter, or the optional
62
- * "alg" argument, must be present.
62
+ * "alg" argument, must be present for asymmetric JSON Web Key imports.
63
63
  *
64
64
  * Note: The JSON Web Key parameters "use", "key_ops", and "ext" are also used in the
65
65
  * {@link !CryptoKey} import process.
66
66
  *
67
+ * Note: Symmetric JSON Web Keys (i.e. `kty: "oct"`) yield back an {@link !Uint8Array} instead of a
68
+ * {@link !CryptoKey}.
69
+ *
67
70
  * This function is exported (as a named export) from the main `'jose'` module entry point as well
68
71
  * as from its subpath export `'jose/key/import'`.
69
72
  *
@@ -233,6 +233,7 @@ export interface GeneralJWS {
233
233
  signatures: Omit<FlattenedJWSInput, 'payload'>[]
234
234
  }
235
235
 
236
+ /** Header Parameters common to JWE and JWS */
236
237
  export interface JoseHeaderParameters {
237
238
  /** "kid" (Key ID) Header Parameter */
238
239
  kid?: string
@@ -584,6 +585,7 @@ export interface JWTPayload {
584
585
  [propName: string]: unknown
585
586
  }
586
587
 
588
+ /** Flattened JWE JSON Serialization Syntax decryption result */
587
589
  export interface FlattenedDecryptResult {
588
590
  /** JWE AAD. */
589
591
  additionalAuthenticatedData?: Uint8Array
@@ -601,8 +603,10 @@ export interface FlattenedDecryptResult {
601
603
  unprotectedHeader?: JWEHeaderParameters
602
604
  }
603
605
 
606
+ /** General JWE JSON Serialization Syntax decryption result */
604
607
  export interface GeneralDecryptResult extends FlattenedDecryptResult {}
605
608
 
609
+ /** Compact JWE decryption result */
606
610
  export interface CompactDecryptResult {
607
611
  /** Plaintext. */
608
612
  plaintext: Uint8Array
@@ -611,6 +615,7 @@ export interface CompactDecryptResult {
611
615
  protectedHeader: CompactJWEHeaderParameters
612
616
  }
613
617
 
618
+ /** Flattened JWS JSON Serialization Syntax verification result */
614
619
  export interface FlattenedVerifyResult {
615
620
  /** JWS Payload. */
616
621
  payload: Uint8Array
@@ -622,8 +627,10 @@ export interface FlattenedVerifyResult {
622
627
  unprotectedHeader?: JWSHeaderParameters
623
628
  }
624
629
 
630
+ /** General JWS JSON Serialization Syntax verification result */
625
631
  export interface GeneralVerifyResult extends FlattenedVerifyResult {}
626
632
 
633
+ /** Compact JWS verification result */
627
634
  export interface CompactVerifyResult {
628
635
  /** JWS Payload. */
629
636
  payload: Uint8Array
@@ -632,6 +639,7 @@ export interface CompactVerifyResult {
632
639
  protectedHeader: CompactJWSHeaderParameters
633
640
  }
634
641
 
642
+ /** Signed JSON Web Token (JWT) verification result */
635
643
  export interface JWTVerifyResult<PayloadType = JWTPayload> {
636
644
  /** JWT Claims Set. */
637
645
  payload: PayloadType & JWTPayload
@@ -640,6 +648,7 @@ export interface JWTVerifyResult<PayloadType = JWTPayload> {
640
648
  protectedHeader: JWTHeaderParameters
641
649
  }
642
650
 
651
+ /** Encrypted JSON Web Token (JWT) decryption result */
643
652
  export interface JWTDecryptResult<PayloadType = JWTPayload> {
644
653
  /** JWT Claims Set. */
645
654
  payload: PayloadType & JWTPayload
@@ -3,22 +3,7 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- /**
7
- * Utility function to encode a string or {@link !Uint8Array} as a base64url string.
8
- *
9
- * @param input Value that will be base64url-encoded.
10
- */
11
- interface Base64UrlEncode {
12
- (input: Uint8Array | string): string;
13
- }
14
- /**
15
- * Utility function to decode a base64url encoded string.
16
- *
17
- * @param input Value that will be base64url-decoded.
18
- */
19
- interface Base64UrlDecode {
20
- (input: Uint8Array | string): Uint8Array;
21
- }
22
- export declare const encode: Base64UrlEncode;
23
- export declare const decode: Base64UrlDecode;
24
- export {};
6
+ /** Decodes a Base64URL encoded input. */
7
+ export declare function decode(input: Uint8Array | string): Uint8Array;
8
+ /** Encodes an input using Base64URL with no padding. */
9
+ export declare function encode(input: Uint8Array | string): string;
@@ -4,6 +4,7 @@
4
4
  * @module
5
5
  */
6
6
  import type * as types from '../types.d.ts';
7
+ /** JWE and JWS Header Parameters */
7
8
  export type ProtectedHeaderParameters = types.JWSHeaderParameters & types.JWEHeaderParameters;
8
9
  /**
9
10
  * Decodes the Protected Header of a JWE/JWS/JWT token utilizing any JOSE serialization.
@@ -1,4 +1,4 @@
1
- import { decode as base64url } from '../../lib/base64url.js';
1
+ import { decode as b64u } from '../../util/base64url.js';
2
2
  import decrypt from '../../lib/decrypt.js';
3
3
  import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js';
4
4
  import isDisjoint from '../../lib/is_disjoint.js';
@@ -44,7 +44,7 @@ export async function flattenedDecrypt(jwe, key, options) {
44
44
  let parsedProt;
45
45
  if (jwe.protected) {
46
46
  try {
47
- const protectedHeader = base64url(jwe.protected);
47
+ const protectedHeader = b64u(jwe.protected);
48
48
  parsedProt = JSON.parse(decoder.decode(protectedHeader));
49
49
  }
50
50
  catch {
@@ -83,7 +83,7 @@ export async function flattenedDecrypt(jwe, key, options) {
83
83
  let encryptedKey;
84
84
  if (jwe.encrypted_key !== undefined) {
85
85
  try {
86
- encryptedKey = base64url(jwe.encrypted_key);
86
+ encryptedKey = b64u(jwe.encrypted_key);
87
87
  }
88
88
  catch {
89
89
  throw new JWEInvalid('Failed to base64url decode the encrypted_key');
@@ -110,7 +110,7 @@ export async function flattenedDecrypt(jwe, key, options) {
110
110
  let tag;
111
111
  if (jwe.iv !== undefined) {
112
112
  try {
113
- iv = base64url(jwe.iv);
113
+ iv = b64u(jwe.iv);
114
114
  }
115
115
  catch {
116
116
  throw new JWEInvalid('Failed to base64url decode the iv');
@@ -118,7 +118,7 @@ export async function flattenedDecrypt(jwe, key, options) {
118
118
  }
119
119
  if (jwe.tag !== undefined) {
120
120
  try {
121
- tag = base64url(jwe.tag);
121
+ tag = b64u(jwe.tag);
122
122
  }
123
123
  catch {
124
124
  throw new JWEInvalid('Failed to base64url decode the tag');
@@ -134,7 +134,7 @@ export async function flattenedDecrypt(jwe, key, options) {
134
134
  }
135
135
  let ciphertext;
136
136
  try {
137
- ciphertext = base64url(jwe.ciphertext);
137
+ ciphertext = b64u(jwe.ciphertext);
138
138
  }
139
139
  catch {
140
140
  throw new JWEInvalid('Failed to base64url decode the ciphertext');
@@ -146,7 +146,7 @@ export async function flattenedDecrypt(jwe, key, options) {
146
146
  }
147
147
  if (jwe.aad !== undefined) {
148
148
  try {
149
- result.additionalAuthenticatedData = base64url(jwe.aad);
149
+ result.additionalAuthenticatedData = b64u(jwe.aad);
150
150
  }
151
151
  catch {
152
152
  throw new JWEInvalid('Failed to base64url decode the aad');
@@ -1,4 +1,4 @@
1
- import { encode as base64url } from '../../lib/base64url.js';
1
+ import { encode as b64u } from '../../util/base64url.js';
2
2
  import { unprotected } from '../../lib/private_symbols.js';
3
3
  import encrypt from '../../lib/encrypt.js';
4
4
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
@@ -123,13 +123,13 @@ export class FlattenedEncrypt {
123
123
  let protectedHeader;
124
124
  let aadMember;
125
125
  if (this._protectedHeader) {
126
- protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader)));
126
+ protectedHeader = encoder.encode(b64u(JSON.stringify(this._protectedHeader)));
127
127
  }
128
128
  else {
129
129
  protectedHeader = encoder.encode('');
130
130
  }
131
131
  if (this._aad) {
132
- aadMember = base64url(this._aad);
132
+ aadMember = b64u(this._aad);
133
133
  additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember));
134
134
  }
135
135
  else {
@@ -137,16 +137,16 @@ export class FlattenedEncrypt {
137
137
  }
138
138
  const { ciphertext, tag, iv } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData);
139
139
  const jwe = {
140
- ciphertext: base64url(ciphertext),
140
+ ciphertext: b64u(ciphertext),
141
141
  };
142
142
  if (iv) {
143
- jwe.iv = base64url(iv);
143
+ jwe.iv = b64u(iv);
144
144
  }
145
145
  if (tag) {
146
- jwe.tag = base64url(tag);
146
+ jwe.tag = b64u(tag);
147
147
  }
148
148
  if (encryptedKey) {
149
- jwe.encrypted_key = base64url(encryptedKey);
149
+ jwe.encrypted_key = b64u(encryptedKey);
150
150
  }
151
151
  if (aadMember) {
152
152
  jwe.aad = aadMember;
@@ -4,7 +4,7 @@ import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
4
4
  import generateCek from '../../lib/cek.js';
5
5
  import isDisjoint from '../../lib/is_disjoint.js';
6
6
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
7
- import { encode as base64url } from '../../lib/base64url.js';
7
+ import { encode as b64u } from '../../util/base64url.js';
8
8
  import validateCrit from '../../lib/validate_crit.js';
9
9
  import normalizeKey from '../../lib/normalize_key.js';
10
10
  import checkKeyType from '../../lib/check_key_type.js';
@@ -178,7 +178,7 @@ export class GeneralEncrypt {
178
178
  checkKeyType(alg === 'dir' ? enc : alg, recipient.key, 'encrypt');
179
179
  const k = await normalizeKey(recipient.key, alg);
180
180
  const { encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, cek, { p2c });
181
- target.encrypted_key = base64url(encryptedKey);
181
+ target.encrypted_key = b64u(encryptedKey);
182
182
  if (recipient.unprotectedHeader || parameters)
183
183
  target.header = { ...recipient.unprotectedHeader, ...parameters };
184
184
  }
@@ -1,5 +1,5 @@
1
1
  import digest from '../lib/digest.js';
2
- import { encode as base64url } from '../lib/base64url.js';
2
+ import { encode as b64u } from '../util/base64url.js';
3
3
  import { JOSENotSupported, JWKInvalid } from '../util/errors.js';
4
4
  import { encoder } from '../lib/buffer_utils.js';
5
5
  import isKeyLike from '../lib/is_key_like.js';
@@ -54,7 +54,7 @@ export async function calculateJwkThumbprint(key, digestAlgorithm) {
54
54
  throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported');
55
55
  }
56
56
  const data = encoder.encode(JSON.stringify(components));
57
- return base64url(await digest(digestAlgorithm, data));
57
+ return b64u(await digest(digestAlgorithm, data));
58
58
  }
59
59
  export async function calculateJwkThumbprintUri(key, digestAlgorithm) {
60
60
  digestAlgorithm ??= 'sha256';
@@ -9,16 +9,16 @@ function isCloudflareWorkers() {
9
9
  let USER_AGENT;
10
10
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
11
11
  const NAME = 'jose';
12
- const VERSION = 'v6.0.5';
12
+ const VERSION = 'v6.0.7';
13
13
  USER_AGENT = `${NAME}/${VERSION}`;
14
14
  }
15
15
  export const customFetch = Symbol();
16
- async function fetchJwks(url, options) {
17
- const response = await (options?.[customFetch] || fetch)(url, {
16
+ async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
17
+ const response = await fetchImpl(url, {
18
18
  method: 'GET',
19
- signal: options.signal,
19
+ signal,
20
20
  redirect: 'manual',
21
- headers: options.headers,
21
+ headers,
22
22
  }).catch((err) => {
23
23
  if (err.name === 'TimeoutError') {
24
24
  throw new JWKSTimeout();
@@ -58,7 +58,8 @@ class RemoteJWKSet {
58
58
  _cacheMaxAge;
59
59
  _jwksTimestamp;
60
60
  _pendingFetch;
61
- _options;
61
+ _headers;
62
+ [customFetch];
62
63
  _local;
63
64
  _cache;
64
65
  constructor(url, options) {
@@ -66,12 +67,20 @@ class RemoteJWKSet {
66
67
  throw new TypeError('url must be an instance of URL');
67
68
  }
68
69
  this._url = new URL(url.href);
69
- this._options = { headers: options?.headers };
70
70
  this._timeoutDuration =
71
71
  typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000;
72
72
  this._cooldownDuration =
73
73
  typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000;
74
74
  this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000;
75
+ this._headers = new Headers(options?.headers);
76
+ if (USER_AGENT && !this._headers.has('User-Agent')) {
77
+ this._headers.set('User-Agent', USER_AGENT);
78
+ }
79
+ if (!this._headers.has('accept')) {
80
+ this._headers.set('accept', 'application/json');
81
+ this._headers.append('accept', 'application/jwk-set+json');
82
+ }
83
+ this[customFetch] = options?.[customFetch];
75
84
  if (options?.[jwksCache] !== undefined) {
76
85
  this._cache = options?.[jwksCache];
77
86
  if (isFreshJwksCache(options?.[jwksCache], this._cacheMaxAge)) {
@@ -111,19 +120,7 @@ class RemoteJWKSet {
111
120
  if (this._pendingFetch && isCloudflareWorkers()) {
112
121
  this._pendingFetch = undefined;
113
122
  }
114
- const headers = new Headers(this._options.headers);
115
- if (USER_AGENT && !headers.has('User-Agent')) {
116
- headers.set('User-Agent', USER_AGENT);
117
- this._options.headers = Object.fromEntries(headers.entries());
118
- }
119
- if (!headers.has('accept')) {
120
- headers.set('accept', 'application/json');
121
- headers.append('accept', 'application/jwk-set+json');
122
- }
123
- this._pendingFetch ||= fetchJwks(this._url.href, {
124
- headers,
125
- signal: AbortSignal.timeout(this._timeoutDuration),
126
- })
123
+ this._pendingFetch ||= fetchJwks(this._url.href, this._headers, AbortSignal.timeout(this._timeoutDuration), this[customFetch])
127
124
  .then((json) => {
128
125
  this._local = createLocalJWKSet(json);
129
126
  if (this._cache) {
@@ -1,4 +1,4 @@
1
- import { encode as base64url } from '../../lib/base64url.js';
1
+ import { encode as b64u } from '../../util/base64url.js';
2
2
  import sign from '../../lib/sign.js';
3
3
  import isDisjoint from '../../lib/is_disjoint.js';
4
4
  import { JWSInvalid } from '../../util/errors.js';
@@ -56,11 +56,11 @@ export class FlattenedSign {
56
56
  checkKeyType(alg, key, 'sign');
57
57
  let payload = this._payload;
58
58
  if (b64) {
59
- payload = encoder.encode(base64url(payload));
59
+ payload = encoder.encode(b64u(payload));
60
60
  }
61
61
  let protectedHeader;
62
62
  if (this._protectedHeader) {
63
- protectedHeader = encoder.encode(base64url(JSON.stringify(this._protectedHeader)));
63
+ protectedHeader = encoder.encode(b64u(JSON.stringify(this._protectedHeader)));
64
64
  }
65
65
  else {
66
66
  protectedHeader = encoder.encode('');
@@ -69,7 +69,7 @@ export class FlattenedSign {
69
69
  const k = await normalizeKey(key, alg);
70
70
  const signature = await sign(alg, k, data);
71
71
  const jws = {
72
- signature: base64url(signature),
72
+ signature: b64u(signature),
73
73
  payload: '',
74
74
  };
75
75
  if (b64) {
@@ -1,4 +1,4 @@
1
- import { decode as base64url } from '../../lib/base64url.js';
1
+ import { decode as b64u } from '../../util/base64url.js';
2
2
  import verify from '../../lib/verify.js';
3
3
  import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';
4
4
  import { concat, encoder, decoder } from '../../lib/buffer_utils.js';
@@ -30,7 +30,7 @@ export async function flattenedVerify(jws, key, options) {
30
30
  let parsedProt = {};
31
31
  if (jws.protected) {
32
32
  try {
33
- const protectedHeader = base64url(jws.protected);
33
+ const protectedHeader = b64u(jws.protected);
34
34
  parsedProt = JSON.parse(decoder.decode(protectedHeader));
35
35
  }
36
36
  catch {
@@ -77,7 +77,7 @@ export async function flattenedVerify(jws, key, options) {
77
77
  const data = concat(encoder.encode(jws.protected ?? ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);
78
78
  let signature;
79
79
  try {
80
- signature = base64url(jws.signature);
80
+ signature = b64u(jws.signature);
81
81
  }
82
82
  catch {
83
83
  throw new JWSInvalid('Failed to base64url decode the signature');
@@ -90,7 +90,7 @@ export async function flattenedVerify(jws, key, options) {
90
90
  let payload;
91
91
  if (b64) {
92
92
  try {
93
- payload = base64url(jws.payload);
93
+ payload = b64u(jws.payload);
94
94
  }
95
95
  catch {
96
96
  throw new JWSInvalid('Failed to base64url decode the payload');
@@ -1,12 +1,12 @@
1
- import * as base64url from '../lib/base64url.js';
1
+ import * as b64u from '../util/base64url.js';
2
2
  import { decoder } from '../lib/buffer_utils.js';
3
3
  import { JWTInvalid } from '../util/errors.js';
4
4
  import jwtPayload from '../lib/jwt_claims_set.js';
5
5
  import { ProduceJWT } from './produce.js';
6
6
  export class UnsecuredJWT extends ProduceJWT {
7
7
  encode() {
8
- const header = base64url.encode(JSON.stringify({ alg: 'none' }));
9
- const payload = base64url.encode(JSON.stringify(this._payload));
8
+ const header = b64u.encode(JSON.stringify({ alg: 'none' }));
9
+ const payload = b64u.encode(JSON.stringify(this._payload));
10
10
  return `${header}.${payload}.`;
11
11
  }
12
12
  static decode(jwt, options) {
@@ -19,14 +19,14 @@ export class UnsecuredJWT extends ProduceJWT {
19
19
  }
20
20
  let header;
21
21
  try {
22
- header = JSON.parse(decoder.decode(base64url.decode(encodedHeader)));
22
+ header = JSON.parse(decoder.decode(b64u.decode(encodedHeader)));
23
23
  if (header.alg !== 'none')
24
24
  throw new Error();
25
25
  }
26
26
  catch {
27
27
  throw new JWTInvalid('Invalid Unsecured JWT');
28
28
  }
29
- const payload = jwtPayload(header, base64url.decode(encodedPayload), options);
29
+ const payload = jwtPayload(header, b64u.decode(encodedPayload), options);
30
30
  return { payload, header };
31
31
  }
32
32
  }
@@ -1,4 +1,4 @@
1
- import { decode as decodeBase64URL } from '../lib/base64url.js';
1
+ import { decode as decodeBase64URL } from '../util/base64url.js';
2
2
  import { fromSPKI, fromPKCS8, fromX509 } from '../lib/asn1.js';
3
3
  import toCryptoKey from '../lib/jwk_to_key.js';
4
4
  import { JOSENotSupported } from '../util/errors.js';
@@ -1,13 +1,13 @@
1
1
  import encrypt from './encrypt.js';
2
2
  import decrypt from './decrypt.js';
3
- import { encode as base64url } from '../lib/base64url.js';
3
+ import { encode as b64u } from '../util/base64url.js';
4
4
  export async function wrap(alg, key, cek, iv) {
5
5
  const jweAlgorithm = alg.slice(0, 7);
6
6
  const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
7
7
  return {
8
8
  encryptedKey: wrapped.ciphertext,
9
- iv: base64url(wrapped.iv),
10
- tag: base64url(wrapped.tag),
9
+ iv: b64u(wrapped.iv),
10
+ tag: b64u(wrapped.tag),
11
11
  };
12
12
  }
13
13
  export async function unwrap(alg, key, encryptedKey, iv, tag) {
@@ -1,5 +1,5 @@
1
1
  import invalidKeyInput from './invalid_key_input.js';
2
- import { encodeBase64, decodeBase64 } from './base64url.js';
2
+ import { encodeBase64, decodeBase64 } from '../lib/base64.js';
3
3
  import { JOSENotSupported } from '../util/errors.js';
4
4
  import { isCryptoKey, isKeyObject } from './is_key_like.js';
5
5
  const formatPEM = (b64, descriptor) => {
@@ -0,0 +1,22 @@
1
+ export function encodeBase64(input) {
2
+ if (Uint8Array.prototype.toBase64) {
3
+ return input.toBase64();
4
+ }
5
+ const CHUNK_SIZE = 0x8000;
6
+ const arr = [];
7
+ for (let i = 0; i < input.length; i += CHUNK_SIZE) {
8
+ arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
9
+ }
10
+ return btoa(arr.join(''));
11
+ }
12
+ export function decodeBase64(encoded) {
13
+ if (Uint8Array.fromBase64) {
14
+ return Uint8Array.fromBase64(encoded);
15
+ }
16
+ const binary = atob(encoded);
17
+ const bytes = new Uint8Array(binary.length);
18
+ for (let i = 0; i < binary.length; i++) {
19
+ bytes[i] = binary.charCodeAt(i);
20
+ }
21
+ return bytes;
22
+ }
@@ -2,7 +2,7 @@ import * as aeskw from './aeskw.js';
2
2
  import * as ecdhes from './ecdhes.js';
3
3
  import * as pbes2kw from './pbes2kw.js';
4
4
  import * as rsaes from './rsaes.js';
5
- import * as base64url from '../lib/base64url.js';
5
+ import { decode as b64u } from '../util/base64url.js';
6
6
  import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
7
7
  import { bitLength as cekLength } from '../lib/cek.js';
8
8
  import { importJWK } from '../key/import.js';
@@ -35,7 +35,7 @@ export default async (alg, key, encryptedKey, joseHeader, options) => {
35
35
  if (typeof joseHeader.apu !== 'string')
36
36
  throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
37
37
  try {
38
- partyUInfo = base64url.decode(joseHeader.apu);
38
+ partyUInfo = b64u(joseHeader.apu);
39
39
  }
40
40
  catch {
41
41
  throw new JWEInvalid('Failed to base64url decode the apu');
@@ -45,7 +45,7 @@ export default async (alg, key, encryptedKey, joseHeader, options) => {
45
45
  if (typeof joseHeader.apv !== 'string')
46
46
  throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
47
47
  try {
48
- partyVInfo = base64url.decode(joseHeader.apv);
48
+ partyVInfo = b64u(joseHeader.apv);
49
49
  }
50
50
  catch {
51
51
  throw new JWEInvalid('Failed to base64url decode the apv');
@@ -81,7 +81,7 @@ export default async (alg, key, encryptedKey, joseHeader, options) => {
81
81
  throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
82
82
  let p2s;
83
83
  try {
84
- p2s = base64url.decode(joseHeader.p2s);
84
+ p2s = b64u(joseHeader.p2s);
85
85
  }
86
86
  catch {
87
87
  throw new JWEInvalid('Failed to base64url decode the p2s');
@@ -106,14 +106,14 @@ export default async (alg, key, encryptedKey, joseHeader, options) => {
106
106
  throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
107
107
  let iv;
108
108
  try {
109
- iv = base64url.decode(joseHeader.iv);
109
+ iv = b64u(joseHeader.iv);
110
110
  }
111
111
  catch {
112
112
  throw new JWEInvalid('Failed to base64url decode the iv');
113
113
  }
114
114
  let tag;
115
115
  try {
116
- tag = base64url.decode(joseHeader.tag);
116
+ tag = b64u(joseHeader.tag);
117
117
  }
118
118
  catch {
119
119
  throw new JWEInvalid('Failed to base64url decode the tag');
@@ -2,7 +2,7 @@ import * as aeskw from './aeskw.js';
2
2
  import * as ecdhes from './ecdhes.js';
3
3
  import * as pbes2kw from './pbes2kw.js';
4
4
  import * as rsaes from './rsaes.js';
5
- import * as base64url from '../lib/base64url.js';
5
+ import { encode as b64u } from '../util/base64url.js';
6
6
  import normalizeKey from './normalize_key.js';
7
7
  import generateCek, { bitLength as cekLength } from '../lib/cek.js';
8
8
  import { JOSENotSupported } from '../util/errors.js';
@@ -40,9 +40,9 @@ export default async (alg, enc, key, providedCek, providedParameters = {}) => {
40
40
  if (kty === 'EC')
41
41
  parameters.epk.y = y;
42
42
  if (apu)
43
- parameters.apu = base64url.encode(apu);
43
+ parameters.apu = b64u(apu);
44
44
  if (apv)
45
- parameters.apv = base64url.encode(apv);
45
+ parameters.apv = b64u(apv);
46
46
  if (alg === 'ECDH-ES') {
47
47
  cek = sharedSecret;
48
48
  break;
@@ -1,5 +1,5 @@
1
1
  import invalidKeyInput from './invalid_key_input.js';
2
- import { encode as base64url } from './base64url.js';
2
+ import { encode as b64u } from '../util/base64url.js';
3
3
  import { isCryptoKey, isKeyObject } from './is_key_like.js';
4
4
  export default async function keyToJWK(key) {
5
5
  if (isKeyObject(key)) {
@@ -13,7 +13,7 @@ export default async function keyToJWK(key) {
13
13
  if (key instanceof Uint8Array) {
14
14
  return {
15
15
  kty: 'oct',
16
- k: base64url(key),
16
+ k: b64u(key),
17
17
  };
18
18
  }
19
19
  if (!isCryptoKey(key)) {
@@ -1,5 +1,5 @@
1
1
  import { isJWK } from './is_jwk.js';
2
- import { decode } from './base64url.js';
2
+ import { decode } from '../util/base64url.js';
3
3
  import importJWK from './jwk_to_key.js';
4
4
  import { isCryptoKey, isKeyObject } from './is_key_like.js';
5
5
  let cache;
@@ -1,4 +1,4 @@
1
- import { encode as base64url } from './base64url.js';
1
+ import { encode as b64u } from '../util/base64url.js';
2
2
  import * as aeskw from './aeskw.js';
3
3
  import { checkEncCryptoKey } from './crypto_key.js';
4
4
  import { concat, encoder } from './buffer_utils.js';
@@ -29,7 +29,7 @@ async function deriveKey(p2s, alg, p2c, key) {
29
29
  export async function wrap(alg, key, cek, p2c = 2048, p2s = crypto.getRandomValues(new Uint8Array(16))) {
30
30
  const derived = await deriveKey(p2s, alg, p2c, key);
31
31
  const encryptedKey = await aeskw.wrap(alg.slice(-6), derived, cek);
32
- return { encryptedKey, p2c, p2s: base64url(p2s) };
32
+ return { encryptedKey, p2c, p2s: b64u(p2s) };
33
33
  }
34
34
  export async function unwrap(alg, key, encryptedKey, p2c, p2s) {
35
35
  const derived = await deriveKey(p2s, alg, p2c, key);
@@ -1,3 +1,30 @@
1
- import * as base64url from '../lib/base64url.js';
2
- export const encode = base64url.encode;
3
- export const decode = base64url.decode;
1
+ import { encoder, decoder } from '../lib/buffer_utils.js';
2
+ import { encodeBase64, decodeBase64 } from '../lib/base64.js';
3
+ export function decode(input) {
4
+ if (Uint8Array.fromBase64) {
5
+ return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
6
+ alphabet: 'base64url',
7
+ });
8
+ }
9
+ let encoded = input;
10
+ if (encoded instanceof Uint8Array) {
11
+ encoded = decoder.decode(encoded);
12
+ }
13
+ encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
14
+ try {
15
+ return decodeBase64(encoded);
16
+ }
17
+ catch {
18
+ throw new TypeError('The input to be decoded is not correctly encoded.');
19
+ }
20
+ }
21
+ export function encode(input) {
22
+ let unencoded = input;
23
+ if (typeof unencoded === 'string') {
24
+ unencoded = encoder.encode(unencoded);
25
+ }
26
+ if (Uint8Array.prototype.toBase64) {
27
+ return unencoded.toBase64({ alphabet: 'base64url', omitPadding: true });
28
+ }
29
+ return encodeBase64(unencoded).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
30
+ }
@@ -1,4 +1,4 @@
1
- import { decode as base64url } from './base64url.js';
1
+ import { decode as b64u } from './base64url.js';
2
2
  import { decoder } from '../lib/buffer_utils.js';
3
3
  import isObject from '../lib/is_object.js';
4
4
  import { JWTInvalid } from './errors.js';
@@ -14,7 +14,7 @@ export function decodeJwt(jwt) {
14
14
  throw new JWTInvalid('JWTs must contain a payload');
15
15
  let decoded;
16
16
  try {
17
- decoded = base64url(payload);
17
+ decoded = b64u(payload);
18
18
  }
19
19
  catch {
20
20
  throw new JWTInvalid('Failed to base64url decode the payload');
@@ -1,4 +1,4 @@
1
- import { decode as base64url } from './base64url.js';
1
+ import { decode as b64u } from './base64url.js';
2
2
  import { decoder } from '../lib/buffer_utils.js';
3
3
  import isObject from '../lib/is_object.js';
4
4
  export function decodeProtectedHeader(token) {
@@ -22,7 +22,7 @@ export function decodeProtectedHeader(token) {
22
22
  if (typeof protectedB64u !== 'string' || !protectedB64u) {
23
23
  throw new Error();
24
24
  }
25
- const result = JSON.parse(decoder.decode(base64url(protectedB64u)));
25
+ const result = JSON.parse(decoder.decode(b64u(protectedB64u)));
26
26
  if (!isObject(result)) {
27
27
  throw new Error();
28
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jose",
3
- "version": "6.0.5",
3
+ "version": "6.0.7",
4
4
  "description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes",
5
5
  "keywords": [
6
6
  "browser",
@@ -1,51 +0,0 @@
1
- import { encoder, decoder } from '../lib/buffer_utils.js';
2
- export function encodeBase64(input) {
3
- if (Uint8Array.prototype.toBase64) {
4
- return input.toBase64();
5
- }
6
- const CHUNK_SIZE = 0x8000;
7
- const arr = [];
8
- for (let i = 0; i < input.length; i += CHUNK_SIZE) {
9
- arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
10
- }
11
- return btoa(arr.join(''));
12
- }
13
- export function encode(input) {
14
- let unencoded = input;
15
- if (typeof unencoded === 'string') {
16
- unencoded = encoder.encode(unencoded);
17
- }
18
- if (Uint8Array.prototype.toBase64) {
19
- return unencoded.toBase64({ alphabet: 'base64url', omitPadding: true });
20
- }
21
- return encodeBase64(unencoded).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
22
- }
23
- export function decodeBase64(encoded) {
24
- if (Uint8Array.fromBase64) {
25
- return Uint8Array.fromBase64(encoded);
26
- }
27
- const binary = atob(encoded);
28
- const bytes = new Uint8Array(binary.length);
29
- for (let i = 0; i < binary.length; i++) {
30
- bytes[i] = binary.charCodeAt(i);
31
- }
32
- return bytes;
33
- }
34
- export function decode(input) {
35
- if (Uint8Array.fromBase64) {
36
- return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
37
- alphabet: 'base64url',
38
- });
39
- }
40
- let encoded = input;
41
- if (encoded instanceof Uint8Array) {
42
- encoded = decoder.decode(encoded);
43
- }
44
- encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
45
- try {
46
- return decodeBase64(encoded);
47
- }
48
- catch {
49
- throw new TypeError('The input to be decoded is not correctly encoded.');
50
- }
51
- }