jose 6.0.13 → 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 +40 -11
  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 +10 -5
  13. package/dist/webapi/jwks/local.js +4 -2
  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 +10 -3
  20. package/dist/webapi/key/import.js +13 -3
  21. package/dist/webapi/lib/aesgcmkw.js +4 -4
  22. package/dist/webapi/lib/asn1.js +9 -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 +9 -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 -13
  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 +19 -4
  44. package/dist/webapi/lib/jwt_claims_set.js +59 -6
  45. package/dist/webapi/lib/key_to_jwk.js +6 -2
  46. package/dist/webapi/lib/normalize_key.js +16 -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 +6 -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 +4 -2
  58. package/dist/webapi/lib/epoch.js +0 -1
  59. package/dist/webapi/lib/secs.js +0 -55
@@ -1,9 +1,62 @@
1
1
  import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';
2
- import { decoder } from './buffer_utils.js';
3
- import epoch from './epoch.js';
4
- import secs from './secs.js';
5
- import isObject from './is_object.js';
6
- import { encoder } from './buffer_utils.js';
2
+ import { encoder, decoder } from './buffer_utils.js';
3
+ import { isObject } from './is_object.js';
4
+ const epoch = (date) => Math.floor(date.getTime() / 1000);
5
+ const minute = 60;
6
+ const hour = minute * 60;
7
+ const day = hour * 24;
8
+ const week = day * 7;
9
+ const year = day * 365.25;
10
+ const REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
11
+ export function secs(str) {
12
+ const matched = REGEX.exec(str);
13
+ if (!matched || (matched[4] && matched[1])) {
14
+ throw new TypeError('Invalid time period format');
15
+ }
16
+ const value = parseFloat(matched[2]);
17
+ const unit = matched[3].toLowerCase();
18
+ let numericDate;
19
+ switch (unit) {
20
+ case 'sec':
21
+ case 'secs':
22
+ case 'second':
23
+ case 'seconds':
24
+ case 's':
25
+ numericDate = Math.round(value);
26
+ break;
27
+ case 'minute':
28
+ case 'minutes':
29
+ case 'min':
30
+ case 'mins':
31
+ case 'm':
32
+ numericDate = Math.round(value * minute);
33
+ break;
34
+ case 'hour':
35
+ case 'hours':
36
+ case 'hr':
37
+ case 'hrs':
38
+ case 'h':
39
+ numericDate = Math.round(value * hour);
40
+ break;
41
+ case 'day':
42
+ case 'days':
43
+ case 'd':
44
+ numericDate = Math.round(value * day);
45
+ break;
46
+ case 'week':
47
+ case 'weeks':
48
+ case 'w':
49
+ numericDate = Math.round(value * week);
50
+ break;
51
+ default:
52
+ numericDate = Math.round(value * year);
53
+ break;
54
+ }
55
+ if (matched[1] === '-' || matched[4] === 'ago') {
56
+ return -numericDate;
57
+ }
58
+ return numericDate;
59
+ }
7
60
  function validateInput(label, input) {
8
61
  if (!Number.isFinite(input)) {
9
62
  throw new TypeError(`Invalid ${label} input`);
@@ -169,7 +222,7 @@ export class JWTClaimsBuilder {
169
222
  }
170
223
  }
171
224
  set iat(value) {
172
- if (typeof value === 'undefined') {
225
+ if (value === undefined) {
173
226
  this.#payload.iat = epoch(new Date());
174
227
  }
175
228
  else if (value instanceof Date) {
@@ -1,7 +1,7 @@
1
- import invalidKeyInput from './invalid_key_input.js';
1
+ import { invalidKeyInput } from './invalid_key_input.js';
2
2
  import { encode as b64u } from '../util/base64url.js';
3
3
  import { isCryptoKey, isKeyObject } from './is_key_like.js';
4
- export default async function keyToJWK(key) {
4
+ export async function keyToJWK(key) {
5
5
  if (isKeyObject(key)) {
6
6
  if (key.type === 'secret') {
7
7
  key = key.export();
@@ -23,5 +23,9 @@ export default async function keyToJWK(key) {
23
23
  throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK');
24
24
  }
25
25
  const { ext, key_ops, alg, use, ...jwk } = await crypto.subtle.exportKey('jwk', key);
26
+ if (jwk.kty === 'AKP') {
27
+ ;
28
+ jwk.alg = alg;
29
+ }
26
30
  return jwk;
27
31
  }
@@ -1,6 +1,6 @@
1
1
  import { isJWK } from './is_jwk.js';
2
2
  import { decode } from '../util/base64url.js';
3
- import importJWK from './jwk_to_key.js';
3
+ import { jwkToKey } from './jwk_to_key.js';
4
4
  import { isCryptoKey, isKeyObject } from './is_key_like.js';
5
5
  let cache;
6
6
  const handleJWK = async (key, jwk, alg, freeze = false) => {
@@ -9,7 +9,7 @@ const handleJWK = async (key, jwk, alg, freeze = false) => {
9
9
  if (cached?.[alg]) {
10
10
  return cached[alg];
11
11
  }
12
- const cryptoKey = await importJWK({ ...jwk, alg });
12
+ const cryptoKey = await jwkToKey({ ...jwk, alg });
13
13
  if (freeze)
14
14
  Object.freeze(key);
15
15
  if (!cached) {
@@ -49,6 +49,18 @@ const handleKeyObject = (keyObject, alg) => {
49
49
  isPublic ? 'verify' : 'sign',
50
50
  ]);
51
51
  }
52
+ switch (keyObject.asymmetricKeyType) {
53
+ case 'ml-dsa-44':
54
+ case 'ml-dsa-65':
55
+ case 'ml-dsa-87': {
56
+ if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {
57
+ throw new TypeError('given KeyObject instance cannot be used for this algorithm');
58
+ }
59
+ cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
60
+ isPublic ? 'verify' : 'sign',
61
+ ]);
62
+ }
63
+ }
52
64
  if (keyObject.asymmetricKeyType === 'rsa') {
53
65
  let hash;
54
66
  switch (alg) {
@@ -130,7 +142,7 @@ const handleKeyObject = (keyObject, alg) => {
130
142
  }
131
143
  return cryptoKey;
132
144
  };
133
- export default async (key, alg) => {
145
+ export async function normalizeKey(key, alg) {
134
146
  if (key instanceof Uint8Array) {
135
147
  return key;
136
148
  }
@@ -161,4 +173,4 @@ export default async (key, alg) => {
161
173
  return handleJWK(key, key, alg, true);
162
174
  }
163
175
  throw new Error('unreachable');
164
- };
176
+ }
@@ -1,16 +1,18 @@
1
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
- import { concat, encoder } from './buffer_utils.js';
4
+ import { concat, encode } from './buffer_utils.js';
5
5
  import { JWEInvalid } from '../util/errors.js';
6
6
  function getCryptoKey(key, alg) {
7
7
  if (key instanceof Uint8Array) {
8
- return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']);
8
+ return crypto.subtle.importKey('raw', key, 'PBKDF2', false, [
9
+ 'deriveBits',
10
+ ]);
9
11
  }
10
12
  checkEncCryptoKey(key, alg, 'deriveBits');
11
13
  return key;
12
14
  }
13
- const concatSalt = (alg, p2sInput) => concat(encoder.encode(alg), new Uint8Array([0]), p2sInput);
15
+ const concatSalt = (alg, p2sInput) => concat(encode(alg), Uint8Array.of(0x00), p2sInput);
14
16
  async function deriveKey(p2s, alg, p2c, key) {
15
17
  if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
16
18
  throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets');
@@ -1,5 +1,5 @@
1
1
  import { checkEncCryptoKey } from './crypto_key.js';
2
- import checkKeyLength from './check_key_length.js';
2
+ import { checkKeyLength } from './check_key_length.js';
3
3
  import { JOSENotSupported } from '../util/errors.js';
4
4
  const subtleAlgorithm = (alg) => {
5
5
  switch (alg) {
@@ -1,9 +1,9 @@
1
- import subtleAlgorithm from './subtle_dsa.js';
2
- import checkKeyLength from './check_key_length.js';
3
- import getSignKey from './get_sign_verify_key.js';
4
- export default async (alg, key, data) => {
5
- const cryptoKey = await getSignKey(alg, key, 'sign');
1
+ import { subtleAlgorithm } from './subtle_dsa.js';
2
+ import { checkKeyLength } from './check_key_length.js';
3
+ import { getSigKey } from './get_sign_verify_key.js';
4
+ export async function sign(alg, key, data) {
5
+ const cryptoKey = await getSigKey(alg, key, 'sign');
6
6
  checkKeyLength(alg, cryptoKey);
7
7
  const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data);
8
8
  return new Uint8Array(signature);
9
- };
9
+ }
@@ -1,5 +1,5 @@
1
1
  import { JOSENotSupported } from '../util/errors.js';
2
- export default (alg, algorithm) => {
2
+ export function subtleAlgorithm(alg, algorithm) {
3
3
  const hash = `SHA-${alg.slice(-3)}`;
4
4
  switch (alg) {
5
5
  case 'HS256':
@@ -21,7 +21,11 @@ export default (alg, algorithm) => {
21
21
  case 'Ed25519':
22
22
  case 'EdDSA':
23
23
  return { name: 'Ed25519' };
24
+ case 'ML-DSA-44':
25
+ case 'ML-DSA-65':
26
+ case 'ML-DSA-87':
27
+ return { name: alg };
24
28
  default:
25
29
  throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
26
30
  }
27
- };
31
+ }
@@ -1,4 +1,4 @@
1
- export default (option, algorithms) => {
1
+ export function validateAlgorithms(option, algorithms) {
2
2
  if (algorithms !== undefined &&
3
3
  (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {
4
4
  throw new TypeError(`"${option}" option must be an array of strings`);
@@ -7,4 +7,4 @@ export default (option, algorithms) => {
7
7
  return undefined;
8
8
  }
9
9
  return new Set(algorithms);
10
- };
10
+ }
@@ -1,5 +1,5 @@
1
1
  import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';
2
- export default (Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) => {
2
+ export function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
3
3
  if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
4
4
  throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
5
5
  }
@@ -30,4 +30,4 @@ export default (Err, recognizedDefault, recognizedOption, protectedHeader, joseH
30
30
  }
31
31
  }
32
32
  return new Set(protectedHeader.crit);
33
- };
33
+ }
@@ -1,8 +1,8 @@
1
- import subtleAlgorithm from './subtle_dsa.js';
2
- import checkKeyLength from './check_key_length.js';
3
- import getVerifyKey from './get_sign_verify_key.js';
4
- export default async (alg, key, signature, data) => {
5
- const cryptoKey = await getVerifyKey(alg, key, 'verify');
1
+ import { subtleAlgorithm } from './subtle_dsa.js';
2
+ import { checkKeyLength } from './check_key_length.js';
3
+ import { getSigKey } from './get_sign_verify_key.js';
4
+ export async function verify(alg, key, signature, data) {
5
+ const cryptoKey = await getSigKey(alg, key, 'verify');
6
6
  checkKeyLength(alg, cryptoKey);
7
7
  const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);
8
8
  try {
@@ -11,4 +11,4 @@ export default async (alg, key, signature, data) => {
11
11
  catch {
12
12
  return false;
13
13
  }
14
- };
14
+ }
@@ -10,7 +10,7 @@ export function decode(input) {
10
10
  if (encoded instanceof Uint8Array) {
11
11
  encoded = decoder.decode(encoded);
12
12
  }
13
- encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
13
+ encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
14
14
  try {
15
15
  return decodeBase64(encoded);
16
16
  }
@@ -1,6 +1,6 @@
1
1
  import { decode as b64u } from './base64url.js';
2
2
  import { decoder } from '../lib/buffer_utils.js';
3
- import isObject from '../lib/is_object.js';
3
+ import { isObject } from '../lib/is_object.js';
4
4
  import { JWTInvalid } from './errors.js';
5
5
  export function decodeJwt(jwt) {
6
6
  if (typeof jwt !== 'string')
@@ -1,6 +1,6 @@
1
1
  import { decode as b64u } from './base64url.js';
2
2
  import { decoder } from '../lib/buffer_utils.js';
3
- import isObject from '../lib/is_object.js';
3
+ import { isObject } from '../lib/is_object.js';
4
4
  export function decodeProtectedHeader(token) {
5
5
  let protectedB64u;
6
6
  if (typeof token === 'string') {
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "jose",
3
- "version": "6.0.13",
3
+ "version": "6.1.1",
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
+ "akp",
6
7
  "browser",
7
8
  "bun",
8
9
  "cloudflare",
@@ -29,8 +30,9 @@
29
30
  "jwk",
30
31
  "jwks",
31
32
  "jws",
32
- "jwt",
33
33
  "jwt-decode",
34
+ "jwt",
35
+ "ml-dsa",
34
36
  "netlify",
35
37
  "next",
36
38
  "nextjs",
@@ -1 +0,0 @@
1
- export default (date) => Math.floor(date.getTime() / 1000);
@@ -1,55 +0,0 @@
1
- const minute = 60;
2
- const hour = minute * 60;
3
- const day = hour * 24;
4
- const week = day * 7;
5
- const year = day * 365.25;
6
- const REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
7
- export default (str) => {
8
- const matched = REGEX.exec(str);
9
- if (!matched || (matched[4] && matched[1])) {
10
- throw new TypeError('Invalid time period format');
11
- }
12
- const value = parseFloat(matched[2]);
13
- const unit = matched[3].toLowerCase();
14
- let numericDate;
15
- switch (unit) {
16
- case 'sec':
17
- case 'secs':
18
- case 'second':
19
- case 'seconds':
20
- case 's':
21
- numericDate = Math.round(value);
22
- break;
23
- case 'minute':
24
- case 'minutes':
25
- case 'min':
26
- case 'mins':
27
- case 'm':
28
- numericDate = Math.round(value * minute);
29
- break;
30
- case 'hour':
31
- case 'hours':
32
- case 'hr':
33
- case 'hrs':
34
- case 'h':
35
- numericDate = Math.round(value * hour);
36
- break;
37
- case 'day':
38
- case 'days':
39
- case 'd':
40
- numericDate = Math.round(value * day);
41
- break;
42
- case 'week':
43
- case 'weeks':
44
- case 'w':
45
- numericDate = Math.round(value * week);
46
- break;
47
- default:
48
- numericDate = Math.round(value * year);
49
- break;
50
- }
51
- if (matched[1] === '-' || matched[4] === 'ago') {
52
- return -numericDate;
53
- }
54
- return numericDate;
55
- };