jose 6.1.0 → 6.1.1

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.
Files changed (59) hide show
  1. package/README.md +3 -2
  2. package/dist/types/jwe/compact/encrypt.d.ts +4 -4
  3. package/dist/types/jwe/flattened/encrypt.d.ts +4 -4
  4. package/dist/types/jwe/general/encrypt.d.ts +9 -0
  5. package/dist/types/jwt/encrypt.d.ts +4 -4
  6. package/dist/types/types.d.ts +14 -5
  7. package/dist/webapi/jwe/flattened/decrypt.js +12 -12
  8. package/dist/webapi/jwe/flattened/encrypt.js +17 -13
  9. package/dist/webapi/jwe/general/decrypt.js +1 -1
  10. package/dist/webapi/jwe/general/encrypt.js +16 -16
  11. package/dist/webapi/jwk/embedded.js +1 -1
  12. package/dist/webapi/jwk/thumbprint.js +5 -5
  13. package/dist/webapi/jwks/local.js +1 -1
  14. package/dist/webapi/jwks/remote.js +2 -2
  15. package/dist/webapi/jws/flattened/sign.js +23 -17
  16. package/dist/webapi/jws/flattened/verify.js +13 -9
  17. package/dist/webapi/jws/general/verify.js +1 -1
  18. package/dist/webapi/key/export.js +1 -1
  19. package/dist/webapi/key/generate_key_pair.js +3 -3
  20. package/dist/webapi/key/import.js +5 -5
  21. package/dist/webapi/lib/aesgcmkw.js +4 -4
  22. package/dist/webapi/lib/asn1.js +3 -7
  23. package/dist/webapi/lib/buffer_utils.js +11 -0
  24. package/dist/webapi/lib/cek.js +2 -2
  25. package/dist/webapi/lib/check_cek_length.js +2 -2
  26. package/dist/webapi/lib/check_iv_length.js +2 -2
  27. package/dist/webapi/lib/check_key_length.js +2 -2
  28. package/dist/webapi/lib/check_key_type.js +13 -17
  29. package/dist/webapi/lib/crypto_key.js +2 -6
  30. package/dist/webapi/lib/decrypt.js +7 -7
  31. package/dist/webapi/lib/decrypt_key_management.js +4 -4
  32. package/dist/webapi/lib/digest.js +2 -2
  33. package/dist/webapi/lib/ecdhes.js +5 -5
  34. package/dist/webapi/lib/encrypt.js +8 -8
  35. package/dist/webapi/lib/encrypt_key_management.js +4 -4
  36. package/dist/webapi/lib/get_sign_verify_key.js +3 -3
  37. package/dist/webapi/lib/invalid_key_input.js +2 -6
  38. package/dist/webapi/lib/is_disjoint.js +2 -2
  39. package/dist/webapi/lib/is_jwk.js +6 -14
  40. package/dist/webapi/lib/is_key_like.js +3 -9
  41. package/dist/webapi/lib/is_object.js +3 -5
  42. package/dist/webapi/lib/iv.js +1 -1
  43. package/dist/webapi/lib/jwk_to_key.js +2 -2
  44. package/dist/webapi/lib/jwt_claims_set.js +59 -6
  45. package/dist/webapi/lib/key_to_jwk.js +2 -2
  46. package/dist/webapi/lib/normalize_key.js +4 -4
  47. package/dist/webapi/lib/pbes2kw.js +5 -3
  48. package/dist/webapi/lib/rsaes.js +1 -1
  49. package/dist/webapi/lib/sign.js +6 -6
  50. package/dist/webapi/lib/subtle_dsa.js +2 -2
  51. package/dist/webapi/lib/validate_algorithms.js +2 -2
  52. package/dist/webapi/lib/validate_crit.js +2 -2
  53. package/dist/webapi/lib/verify.js +6 -6
  54. package/dist/webapi/util/base64url.js +1 -1
  55. package/dist/webapi/util/decode_jwt.js +1 -1
  56. package/dist/webapi/util/decode_protected_header.js +1 -1
  57. package/package.json +1 -1
  58. package/dist/webapi/lib/epoch.js +0 -1
  59. package/dist/webapi/lib/secs.js +0 -55
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # jose
2
2
 
3
- `jose` is JavaScript module for JSON Object Signing and Encryption, providing support for JSON Web Tokens (JWT), JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), JSON Web Key Set (JWKS), and more. The module is designed to work across various Web-interoperable runtimes including Node.js, browsers, Cloudflare Workers, Deno, Bun, and others.
3
+ `jose` is a JavaScript module for JSON Object Signing and Encryption, providing support for JSON Web Tokens (JWT), JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), JSON Web Key Set (JWKS), and more. The module is designed to work across various Web-interoperable runtimes including Node.js, browsers, Cloudflare Workers, Deno, Bun, and others.
4
4
 
5
5
  ## Sponsor
6
6
 
@@ -110,7 +110,6 @@ The following runtimes are supported _(this is not an exhaustive list)_:
110
110
  - [Deno](https://github.com/panva/jose/issues/266)
111
111
  - [Electron](https://github.com/panva/jose/issues/264)
112
112
  - [Node.js](https://github.com/panva/jose/issues/262)
113
- - [Vercel's Edge Runtime](https://github.com/panva/jose/issues/301)
114
113
 
115
114
  Please note that certain algorithms may not be available depending on the runtime used. You can find a list of available algorithms for each runtime in the specific issue links provided above.
116
115
 
@@ -137,6 +136,8 @@ Please note that certain algorithms may not be available depending on the runtim
137
136
  - JSON Web Key Thumbprint URI - [RFC9278](https://www.rfc-editor.org/rfc/rfc9278)
138
137
  - JWS Unencoded Payload Option - [RFC7797](https://www.rfc-editor.org/rfc/rfc7797)
139
138
  - CFRG Elliptic Curve ECDH and Signatures - [RFC8037](https://www.rfc-editor.org/rfc/rfc8037)
139
+ - Fully-Specified Algorithms for JOSE - [RFC9864](https://www.rfc-editor.org/rfc/rfc9864.html)
140
+ - ML-DSA for JOSE - [draft-ietf-cose-dilithium-10](https://www.ietf.org/archive/id/draft-ietf-cose-dilithium-10.html)
140
141
 
141
142
  The algorithm implementations in `jose` have been tested using test vectors from their respective specifications as well as [RFC7520](https://www.rfc-editor.org/rfc/rfc7520).
142
143
 
@@ -46,10 +46,10 @@ export declare class CompactEncrypt {
46
46
  */
47
47
  setProtectedHeader(protectedHeader: types.CompactJWEHeaderParameters): this;
48
48
  /**
49
- * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is
50
- * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or
51
- * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed
52
- * and missing.
49
+ * Sets the JWE Key Management parameters to be used when encrypting.
50
+ *
51
+ * (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
52
+ * PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
53
53
  *
54
54
  * @param parameters JWE Key Management parameters.
55
55
  */
@@ -20,10 +20,10 @@ export declare class FlattenedEncrypt {
20
20
  */
21
21
  constructor(plaintext: Uint8Array);
22
22
  /**
23
- * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is
24
- * really only needed for ECDH based algorithms when utilizing the "apu" (Agreement PartyUInfo) or
25
- * "apv" (Agreement PartyVInfo) parameters. Other parameters will always be randomly generated
26
- * when needed and missing.
23
+ * Sets the JWE Key Management parameters to be used when encrypting.
24
+ *
25
+ * (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
26
+ * PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
27
27
  *
28
28
  * @param parameters JWE Key Management parameters.
29
29
  */
@@ -12,6 +12,15 @@ export interface Recipient {
12
12
  * @param unprotectedHeader JWE Per-Recipient Unprotected Header.
13
13
  */
14
14
  setUnprotectedHeader(unprotectedHeader: types.JWEHeaderParameters): Recipient;
15
+ /**
16
+ * Sets the JWE Key Management parameters to be used when encrypting.
17
+ *
18
+ * (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
19
+ * PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
20
+ *
21
+ * @param parameters JWE Key Management parameters.
22
+ */
23
+ setKeyManagementParameters(parameters: types.JWEKeyManagementHeaderParameters): Recipient;
15
24
  /** A shorthand for calling addRecipient() on the enclosing {@link GeneralEncrypt} instance */
16
25
  addRecipient(...args: Parameters<GeneralEncrypt['addRecipient']>): Recipient;
17
26
  /** A shorthand for calling encrypt() on the enclosing {@link GeneralEncrypt} instance */
@@ -34,10 +34,10 @@ export declare class EncryptJWT implements types.ProduceJWT {
34
34
  */
35
35
  setProtectedHeader(protectedHeader: types.CompactJWEHeaderParameters): this;
36
36
  /**
37
- * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is
38
- * really only needed for ECDH based algorithms when utilizing the "apu" (Agreement PartyUInfo) or
39
- * "apv" (Agreement PartyVInfo) parameters. Other parameters will always be randomly generated
40
- * when needed and missing.
37
+ * Sets the JWE Key Management parameters to be used when encrypting.
38
+ *
39
+ * (ECDH-ES) Use of this method is needed for ECDH based algorithms to set the "apu" (Agreement
40
+ * PartyUInfo) or "apv" (Agreement PartyVInfo) parameters.
41
41
  *
42
42
  * @param parameters JWE Key Management parameters.
43
43
  */
@@ -165,7 +165,7 @@ export interface GenericGetKeyFunction<IProtectedHeader, IToken, ReturnKeyTypes>
165
165
  * Dynamic key resolution function. No token components have been verified at the time of this
166
166
  * function call.
167
167
  *
168
- * If you cannot match a key suitable for the token, throw an error instead.
168
+ * If a suitable key for the token cannot be matched, throw an error instead.
169
169
  *
170
170
  * @param protectedHeader JWE or JWS Protected Header.
171
171
  * @param token The consumed JWE or JWS token.
@@ -304,25 +304,34 @@ export interface JWSHeaderParameters extends JoseHeaderParameters {
304
304
 
305
305
  /** Recognized JWE Key Management-related Header Parameters. */
306
306
  export interface JWEKeyManagementHeaderParameters {
307
+ /**
308
+ * ECDH-ES "apu" (Agreement PartyUInfo). This will be used as a JOSE Header Parameter and will be
309
+ * used in ECDH's ConcatKDF.
310
+ */
307
311
  apu?: Uint8Array
312
+
313
+ /**
314
+ * ECDH-ES "apv" (Agreement PartyVInfo). This will be used as a JOSE Header Parameter and will be
315
+ * used in ECDH's ConcatKDF.
316
+ */
308
317
  apv?: Uint8Array
309
318
  /**
310
- * @deprecated You should not use this parameter. It is only really intended for test and vector
319
+ * @deprecated You should not use this parameter. It is only intended for testing and vector
311
320
  * validation purposes.
312
321
  */
313
322
  p2c?: number
314
323
  /**
315
- * @deprecated You should not use this parameter. It is only really intended for test and vector
324
+ * @deprecated You should not use this parameter. It is only intended for testing and vector
316
325
  * validation purposes.
317
326
  */
318
327
  p2s?: Uint8Array
319
328
  /**
320
- * @deprecated You should not use this parameter. It is only really intended for test and vector
329
+ * @deprecated You should not use this parameter. It is only intended for testing and vector
321
330
  * validation purposes.
322
331
  */
323
332
  iv?: Uint8Array
324
333
  /**
325
- * @deprecated You should not use this parameter. It is only really intended for test and vector
334
+ * @deprecated You should not use this parameter. It is only intended for testing and vector
326
335
  * validation purposes.
327
336
  */
328
337
  epk?: CryptoKey | KeyObject
@@ -1,15 +1,15 @@
1
1
  import { decode as b64u } from '../../util/base64url.js';
2
- import decrypt from '../../lib/decrypt.js';
2
+ import { decrypt } from '../../lib/decrypt.js';
3
3
  import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js';
4
- import isDisjoint from '../../lib/is_disjoint.js';
5
- import isObject from '../../lib/is_object.js';
6
- import decryptKeyManagement from '../../lib/decrypt_key_management.js';
7
- import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
8
- import generateCek from '../../lib/cek.js';
9
- import validateCrit from '../../lib/validate_crit.js';
10
- import validateAlgorithms from '../../lib/validate_algorithms.js';
11
- import normalizeKey from '../../lib/normalize_key.js';
12
- import checkKeyType from '../../lib/check_key_type.js';
4
+ import { isDisjoint } from '../../lib/is_disjoint.js';
5
+ import { isObject } from '../../lib/is_object.js';
6
+ import { decryptKeyManagement } from '../../lib/decrypt_key_management.js';
7
+ import { decoder, concat, encode } from '../../lib/buffer_utils.js';
8
+ import { generateCek } from '../../lib/cek.js';
9
+ import { validateCrit } from '../../lib/validate_crit.js';
10
+ import { validateAlgorithms } from '../../lib/validate_algorithms.js';
11
+ import { normalizeKey } from '../../lib/normalize_key.js';
12
+ import { checkKeyType } from '../../lib/check_key_type.js';
13
13
  export async function flattenedDecrypt(jwe, key, options) {
14
14
  if (!isObject(jwe)) {
15
15
  throw new JWEInvalid('Flattened JWE must be an object');
@@ -124,10 +124,10 @@ export async function flattenedDecrypt(jwe, key, options) {
124
124
  throw new JWEInvalid('Failed to base64url decode the tag');
125
125
  }
126
126
  }
127
- const protectedHeader = encoder.encode(jwe.protected ?? '');
127
+ const protectedHeader = jwe.protected !== undefined ? encode(jwe.protected) : new Uint8Array();
128
128
  let additionalData;
129
129
  if (jwe.aad !== undefined) {
130
- additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(jwe.aad));
130
+ additionalData = concat(protectedHeader, encode('.'), encode(jwe.aad));
131
131
  }
132
132
  else {
133
133
  additionalData = protectedHeader;
@@ -1,13 +1,13 @@
1
1
  import { encode as b64u } from '../../util/base64url.js';
2
2
  import { unprotected } from '../../lib/private_symbols.js';
3
- import encrypt from '../../lib/encrypt.js';
4
- import encryptKeyManagement from '../../lib/encrypt_key_management.js';
3
+ import { encrypt } from '../../lib/encrypt.js';
4
+ import { encryptKeyManagement } from '../../lib/encrypt_key_management.js';
5
5
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
6
- import isDisjoint from '../../lib/is_disjoint.js';
7
- import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
8
- import validateCrit from '../../lib/validate_crit.js';
9
- import normalizeKey from '../../lib/normalize_key.js';
10
- import checkKeyType from '../../lib/check_key_type.js';
6
+ import { isDisjoint } from '../../lib/is_disjoint.js';
7
+ import { concat, encode } from '../../lib/buffer_utils.js';
8
+ import { validateCrit } from '../../lib/validate_crit.js';
9
+ import { normalizeKey } from '../../lib/normalize_key.js';
10
+ import { checkKeyType } from '../../lib/check_key_type.js';
11
11
  export class FlattenedEncrypt {
12
12
  #plaintext;
13
13
  #protectedHeader;
@@ -120,20 +120,24 @@ export class FlattenedEncrypt {
120
120
  }
121
121
  }
122
122
  let additionalData;
123
- let protectedHeader;
123
+ let protectedHeaderS;
124
+ let protectedHeaderB;
124
125
  let aadMember;
125
126
  if (this.#protectedHeader) {
126
- protectedHeader = encoder.encode(b64u(JSON.stringify(this.#protectedHeader)));
127
+ protectedHeaderS = b64u(JSON.stringify(this.#protectedHeader));
128
+ protectedHeaderB = encode(protectedHeaderS);
127
129
  }
128
130
  else {
129
- protectedHeader = encoder.encode('');
131
+ protectedHeaderS = '';
132
+ protectedHeaderB = new Uint8Array();
130
133
  }
131
134
  if (this.#aad) {
132
135
  aadMember = b64u(this.#aad);
133
- additionalData = concat(protectedHeader, encoder.encode('.'), encoder.encode(aadMember));
136
+ const aadMemberBytes = encode(aadMember);
137
+ additionalData = concat(protectedHeaderB, encode('.'), aadMemberBytes);
134
138
  }
135
139
  else {
136
- additionalData = protectedHeader;
140
+ additionalData = protectedHeaderB;
137
141
  }
138
142
  const { ciphertext, tag, iv } = await encrypt(enc, this.#plaintext, cek, this.#iv, additionalData);
139
143
  const jwe = {
@@ -152,7 +156,7 @@ export class FlattenedEncrypt {
152
156
  jwe.aad = aadMember;
153
157
  }
154
158
  if (this.#protectedHeader) {
155
- jwe.protected = decoder.decode(protectedHeader);
159
+ jwe.protected = protectedHeaderS;
156
160
  }
157
161
  if (this.#sharedUnprotectedHeader) {
158
162
  jwe.unprotected = this.#sharedUnprotectedHeader;
@@ -1,6 +1,6 @@
1
1
  import { flattenedDecrypt } from '../flattened/decrypt.js';
2
2
  import { JWEDecryptionFailed, JWEInvalid } from '../../util/errors.js';
3
- import isObject from '../../lib/is_object.js';
3
+ import { isObject } from '../../lib/is_object.js';
4
4
  export async function generalDecrypt(jwe, key, options) {
5
5
  if (!isObject(jwe)) {
6
6
  throw new JWEInvalid('General JWE must be an object');
@@ -1,16 +1,17 @@
1
1
  import { FlattenedEncrypt } from '../flattened/encrypt.js';
2
2
  import { unprotected } from '../../lib/private_symbols.js';
3
3
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
4
- import generateCek from '../../lib/cek.js';
5
- import isDisjoint from '../../lib/is_disjoint.js';
6
- import encryptKeyManagement from '../../lib/encrypt_key_management.js';
4
+ import { generateCek } from '../../lib/cek.js';
5
+ import { isDisjoint } from '../../lib/is_disjoint.js';
6
+ import { encryptKeyManagement } from '../../lib/encrypt_key_management.js';
7
7
  import { encode as b64u } from '../../util/base64url.js';
8
- import validateCrit from '../../lib/validate_crit.js';
9
- import normalizeKey from '../../lib/normalize_key.js';
10
- import checkKeyType from '../../lib/check_key_type.js';
8
+ import { validateCrit } from '../../lib/validate_crit.js';
9
+ import { normalizeKey } from '../../lib/normalize_key.js';
10
+ import { checkKeyType } from '../../lib/check_key_type.js';
11
11
  class IndividualRecipient {
12
12
  #parent;
13
13
  unprotectedHeader;
14
+ keyManagementParameters;
14
15
  key;
15
16
  options;
16
17
  constructor(enc, key, options) {
@@ -25,6 +26,13 @@ class IndividualRecipient {
25
26
  this.unprotectedHeader = unprotectedHeader;
26
27
  return this;
27
28
  }
29
+ setKeyManagementParameters(parameters) {
30
+ if (this.keyManagementParameters) {
31
+ throw new TypeError('setKeyManagementParameters can only be called once');
32
+ }
33
+ this.keyManagementParameters = parameters;
34
+ return this;
35
+ }
28
36
  addRecipient(...args) {
29
37
  return this.#parent.addRecipient(...args);
30
38
  }
@@ -132,20 +140,12 @@ export class GeneralEncrypt {
132
140
  const cek = generateCek(enc);
133
141
  const jwe = {
134
142
  ciphertext: '',
135
- iv: '',
136
143
  recipients: [],
137
- tag: '',
138
144
  };
139
145
  for (let i = 0; i < this.#recipients.length; i++) {
140
146
  const recipient = this.#recipients[i];
141
147
  const target = {};
142
148
  jwe.recipients.push(target);
143
- const joseHeader = {
144
- ...this.#protectedHeader,
145
- ...this.#unprotectedHeader,
146
- ...recipient.unprotectedHeader,
147
- };
148
- const p2c = joseHeader.alg.startsWith('PBES2') ? 2048 + i : undefined;
149
149
  if (i === 0) {
150
150
  const flattened = await new FlattenedEncrypt(this.#plaintext)
151
151
  .setAdditionalAuthenticatedData(this.#aad)
@@ -153,7 +153,7 @@ export class GeneralEncrypt {
153
153
  .setProtectedHeader(this.#protectedHeader)
154
154
  .setSharedUnprotectedHeader(this.#unprotectedHeader)
155
155
  .setUnprotectedHeader(recipient.unprotectedHeader)
156
- .setKeyManagementParameters({ p2c })
156
+ .setKeyManagementParameters(recipient.keyManagementParameters)
157
157
  .encrypt(recipient.key, {
158
158
  ...recipient.options,
159
159
  [unprotected]: true,
@@ -177,7 +177,7 @@ export class GeneralEncrypt {
177
177
  this.#unprotectedHeader?.alg;
178
178
  checkKeyType(alg === 'dir' ? enc : alg, recipient.key, 'encrypt');
179
179
  const k = await normalizeKey(recipient.key, alg);
180
- const { encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, cek, { p2c });
180
+ const { encryptedKey, parameters } = await encryptKeyManagement(alg, enc, k, cek, recipient.keyManagementParameters);
181
181
  target.encrypted_key = b64u(encryptedKey);
182
182
  if (recipient.unprotectedHeader || parameters)
183
183
  target.header = { ...recipient.unprotectedHeader, ...parameters };
@@ -1,5 +1,5 @@
1
1
  import { importJWK } from '../key/import.js';
2
- import isObject from '../lib/is_object.js';
2
+ import { isObject } from '../lib/is_object.js';
3
3
  import { JWSInvalid } from '../util/errors.js';
4
4
  export async function EmbeddedJWK(protectedHeader, token) {
5
5
  const joseHeader = {
@@ -1,11 +1,11 @@
1
- import digest from '../lib/digest.js';
1
+ import { digest } from '../lib/digest.js';
2
2
  import { encode as b64u } from '../util/base64url.js';
3
3
  import { JOSENotSupported, JWKInvalid } from '../util/errors.js';
4
- import { encoder } from '../lib/buffer_utils.js';
5
- import isKeyLike from '../lib/is_key_like.js';
4
+ import { encode } from '../lib/buffer_utils.js';
5
+ import { isKeyLike } from '../lib/is_key_like.js';
6
6
  import { isJWK } from '../lib/is_jwk.js';
7
7
  import { exportJWK } from '../key/export.js';
8
- import invalidKeyInput from '../lib/invalid_key_input.js';
8
+ import { invalidKeyInput } from '../lib/invalid_key_input.js';
9
9
  const check = (value, description) => {
10
10
  if (typeof value !== 'string' || !value) {
11
11
  throw new JWKInvalid(`${description} missing or invalid`);
@@ -58,7 +58,7 @@ export async function calculateJwkThumbprint(key, digestAlgorithm) {
58
58
  default:
59
59
  throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported');
60
60
  }
61
- const data = encoder.encode(JSON.stringify(components));
61
+ const data = encode(JSON.stringify(components));
62
62
  return b64u(await digest(digestAlgorithm, data));
63
63
  }
64
64
  export async function calculateJwkThumbprintUri(key, digestAlgorithm) {
@@ -1,6 +1,6 @@
1
1
  import { importJWK } from '../key/import.js';
2
2
  import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';
3
- import isObject from '../lib/is_object.js';
3
+ import { isObject } from '../lib/is_object.js';
4
4
  function getKtyFromAlg(alg) {
5
5
  switch (typeof alg === 'string' && alg.slice(0, 2)) {
6
6
  case 'RS':
@@ -1,6 +1,6 @@
1
1
  import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from '../util/errors.js';
2
2
  import { createLocalJWKSet } from './local.js';
3
- import isObject from '../lib/is_object.js';
3
+ import { isObject } from '../lib/is_object.js';
4
4
  function isCloudflareWorkers() {
5
5
  return (typeof WebSocketPair !== 'undefined' ||
6
6
  (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||
@@ -9,7 +9,7 @@ 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.1.0';
12
+ const VERSION = 'v6.1.1';
13
13
  USER_AGENT = `${NAME}/${VERSION}`;
14
14
  }
15
15
  export const customFetch = Symbol();
@@ -1,11 +1,11 @@
1
1
  import { encode as b64u } from '../../util/base64url.js';
2
- import sign from '../../lib/sign.js';
3
- import isDisjoint from '../../lib/is_disjoint.js';
2
+ import { sign } from '../../lib/sign.js';
3
+ import { isDisjoint } from '../../lib/is_disjoint.js';
4
4
  import { JWSInvalid } from '../../util/errors.js';
5
- import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
6
- import checkKeyType from '../../lib/check_key_type.js';
7
- import validateCrit from '../../lib/validate_crit.js';
8
- import normalizeKey from '../../lib/normalize_key.js';
5
+ import { concat, encode } from '../../lib/buffer_utils.js';
6
+ import { checkKeyType } from '../../lib/check_key_type.js';
7
+ import { validateCrit } from '../../lib/validate_crit.js';
8
+ import { normalizeKey } from '../../lib/normalize_key.js';
9
9
  export class FlattenedSign {
10
10
  #payload;
11
11
  #protectedHeader;
@@ -54,32 +54,38 @@ export class FlattenedSign {
54
54
  throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
55
55
  }
56
56
  checkKeyType(alg, key, 'sign');
57
- let payload = this.#payload;
57
+ let payloadS;
58
+ let payloadB;
58
59
  if (b64) {
59
- payload = encoder.encode(b64u(payload));
60
+ payloadS = b64u(this.#payload);
61
+ payloadB = encode(payloadS);
60
62
  }
61
- let protectedHeader;
63
+ else {
64
+ payloadB = this.#payload;
65
+ payloadS = '';
66
+ }
67
+ let protectedHeaderString;
68
+ let protectedHeaderBytes;
62
69
  if (this.#protectedHeader) {
63
- protectedHeader = encoder.encode(b64u(JSON.stringify(this.#protectedHeader)));
70
+ protectedHeaderString = b64u(JSON.stringify(this.#protectedHeader));
71
+ protectedHeaderBytes = encode(protectedHeaderString);
64
72
  }
65
73
  else {
66
- protectedHeader = encoder.encode('');
74
+ protectedHeaderString = '';
75
+ protectedHeaderBytes = new Uint8Array();
67
76
  }
68
- const data = concat(protectedHeader, encoder.encode('.'), payload);
77
+ const data = concat(protectedHeaderBytes, encode('.'), payloadB);
69
78
  const k = await normalizeKey(key, alg);
70
79
  const signature = await sign(alg, k, data);
71
80
  const jws = {
72
81
  signature: b64u(signature),
73
- payload: '',
82
+ payload: payloadS,
74
83
  };
75
- if (b64) {
76
- jws.payload = decoder.decode(payload);
77
- }
78
84
  if (this.#unprotectedHeader) {
79
85
  jws.header = this.#unprotectedHeader;
80
86
  }
81
87
  if (this.#protectedHeader) {
82
- jws.protected = decoder.decode(protectedHeader);
88
+ jws.protected = protectedHeaderString;
83
89
  }
84
90
  return jws;
85
91
  }
@@ -1,13 +1,13 @@
1
1
  import { decode as b64u } from '../../util/base64url.js';
2
- import verify from '../../lib/verify.js';
2
+ import { verify } from '../../lib/verify.js';
3
3
  import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';
4
- import { concat, encoder, decoder } from '../../lib/buffer_utils.js';
5
- import isDisjoint from '../../lib/is_disjoint.js';
6
- import isObject from '../../lib/is_object.js';
7
- import checkKeyType from '../../lib/check_key_type.js';
8
- import validateCrit from '../../lib/validate_crit.js';
9
- import validateAlgorithms from '../../lib/validate_algorithms.js';
10
- import normalizeKey from '../../lib/normalize_key.js';
4
+ import { concat, encoder, decoder, encode } from '../../lib/buffer_utils.js';
5
+ import { isDisjoint } from '../../lib/is_disjoint.js';
6
+ import { isObject } from '../../lib/is_object.js';
7
+ import { checkKeyType } from '../../lib/check_key_type.js';
8
+ import { validateCrit } from '../../lib/validate_crit.js';
9
+ import { validateAlgorithms } from '../../lib/validate_algorithms.js';
10
+ import { normalizeKey } from '../../lib/normalize_key.js';
11
11
  export async function flattenedVerify(jws, key, options) {
12
12
  if (!isObject(jws)) {
13
13
  throw new JWSInvalid('Flattened JWS must be an object');
@@ -74,7 +74,11 @@ export async function flattenedVerify(jws, key, options) {
74
74
  resolvedKey = true;
75
75
  }
76
76
  checkKeyType(alg, key, 'verify');
77
- const data = concat(encoder.encode(jws.protected ?? ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);
77
+ const data = concat(jws.protected !== undefined ? encode(jws.protected) : new Uint8Array(), encode('.'), typeof jws.payload === 'string'
78
+ ? b64
79
+ ? encode(jws.payload)
80
+ : encoder.encode(jws.payload)
81
+ : jws.payload);
78
82
  let signature;
79
83
  try {
80
84
  signature = b64u(jws.signature);
@@ -1,6 +1,6 @@
1
1
  import { flattenedVerify } from '../flattened/verify.js';
2
2
  import { JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';
3
- import isObject from '../../lib/is_object.js';
3
+ import { isObject } from '../../lib/is_object.js';
4
4
  export async function generalVerify(jws, key, options) {
5
5
  if (!isObject(jws)) {
6
6
  throw new JWSInvalid('General JWS must be an object');
@@ -1,5 +1,5 @@
1
1
  import { toSPKI as exportPublic, toPKCS8 as exportPrivate } from '../lib/asn1.js';
2
- import keyToJWK from '../lib/key_to_jwk.js';
2
+ import { keyToJWK } from '../lib/key_to_jwk.js';
3
3
  export async function exportSPKI(key) {
4
4
  return exportPublic(key);
5
5
  }
@@ -16,7 +16,7 @@ export async function generateKeyPair(alg, options) {
16
16
  algorithm = {
17
17
  name: 'RSA-PSS',
18
18
  hash: `SHA-${alg.slice(-3)}`,
19
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
19
+ publicExponent: Uint8Array.of(0x01, 0x00, 0x01),
20
20
  modulusLength: getModulusLengthOption(options),
21
21
  };
22
22
  keyUsages = ['sign', 'verify'];
@@ -27,7 +27,7 @@ export async function generateKeyPair(alg, options) {
27
27
  algorithm = {
28
28
  name: 'RSASSA-PKCS1-v1_5',
29
29
  hash: `SHA-${alg.slice(-3)}`,
30
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
30
+ publicExponent: Uint8Array.of(0x01, 0x00, 0x01),
31
31
  modulusLength: getModulusLengthOption(options),
32
32
  };
33
33
  keyUsages = ['sign', 'verify'];
@@ -39,7 +39,7 @@ export async function generateKeyPair(alg, options) {
39
39
  algorithm = {
40
40
  name: 'RSA-OAEP',
41
41
  hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`,
42
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
42
+ publicExponent: Uint8Array.of(0x01, 0x00, 0x01),
43
43
  modulusLength: getModulusLengthOption(options),
44
44
  };
45
45
  keyUsages = ['decrypt', 'unwrapKey', 'encrypt', 'wrapKey'];
@@ -1,8 +1,8 @@
1
1
  import { decode as decodeBase64URL } from '../util/base64url.js';
2
2
  import { fromSPKI, fromPKCS8, fromX509 } from '../lib/asn1.js';
3
- import toCryptoKey from '../lib/jwk_to_key.js';
3
+ import { jwkToKey } from '../lib/jwk_to_key.js';
4
4
  import { JOSENotSupported } from '../util/errors.js';
5
- import isObject from '../lib/is_object.js';
5
+ import { isObject } from '../lib/is_object.js';
6
6
  export async function importSPKI(spki, alg, options) {
7
7
  if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {
8
8
  throw new TypeError('"spki" must be SPKI formatted string');
@@ -38,7 +38,7 @@ export async function importJWK(jwk, alg, options) {
38
38
  if ('oth' in jwk && jwk.oth !== undefined) {
39
39
  throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
40
40
  }
41
- return toCryptoKey({ ...jwk, alg, ext });
41
+ return jwkToKey({ ...jwk, alg, ext });
42
42
  case 'AKP': {
43
43
  if (typeof jwk.alg !== 'string' || !jwk.alg) {
44
44
  throw new TypeError('missing "alg" (Algorithm) Parameter value');
@@ -46,11 +46,11 @@ export async function importJWK(jwk, alg, options) {
46
46
  if (alg !== undefined && alg !== jwk.alg) {
47
47
  throw new TypeError('JWK alg and alg option value mismatch');
48
48
  }
49
- return toCryptoKey({ ...jwk, ext });
49
+ return jwkToKey({ ...jwk, ext });
50
50
  }
51
51
  case 'EC':
52
52
  case 'OKP':
53
- return toCryptoKey({ ...jwk, alg, ext });
53
+ return jwkToKey({ ...jwk, alg, ext });
54
54
  default:
55
55
  throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
56
56
  }
@@ -1,9 +1,9 @@
1
- import encrypt from './encrypt.js';
2
- import decrypt from './decrypt.js';
1
+ import { encrypt } from './encrypt.js';
2
+ import { decrypt } from './decrypt.js';
3
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
- const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
6
+ const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array());
7
7
  return {
8
8
  encryptedKey: wrapped.ciphertext,
9
9
  iv: b64u(wrapped.iv),
@@ -12,5 +12,5 @@ export async function wrap(alg, key, cek, iv) {
12
12
  }
13
13
  export async function unwrap(alg, key, encryptedKey, iv, tag) {
14
14
  const jweAlgorithm = alg.slice(0, 7);
15
- return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
15
+ return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array());
16
16
  }
@@ -1,4 +1,4 @@
1
- import invalidKeyInput from './invalid_key_input.js';
1
+ import { invalidKeyInput } from './invalid_key_input.js';
2
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';
@@ -24,12 +24,8 @@ const genericExport = async (keyType, keyFormat, key) => {
24
24
  }
25
25
  return formatPEM(encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`);
26
26
  };
27
- export const toSPKI = (key) => {
28
- return genericExport('public', 'spki', key);
29
- };
30
- export const toPKCS8 = (key) => {
31
- return genericExport('private', 'pkcs8', key);
32
- };
27
+ export const toSPKI = (key) => genericExport('public', 'spki', key);
28
+ export const toPKCS8 = (key) => genericExport('private', 'pkcs8', key);
33
29
  const bytesEqual = (a, b) => {
34
30
  if (a.byteLength !== b.length)
35
31
  return false;
@@ -30,3 +30,14 @@ export function uint32be(value) {
30
30
  writeUInt32BE(buf, value);
31
31
  return buf;
32
32
  }
33
+ export function encode(string) {
34
+ const bytes = new Uint8Array(string.length);
35
+ for (let i = 0; i < string.length; i++) {
36
+ const code = string.charCodeAt(i);
37
+ if (code > 127) {
38
+ throw new TypeError('non-ASCII string encountered in encode()');
39
+ }
40
+ bytes[i] = code;
41
+ }
42
+ return bytes;
43
+ }