jose 3.16.0 → 3.19.0

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 (108) hide show
  1. package/README.md +22 -114
  2. package/dist/browser/jwe/compact/decrypt.js +5 -1
  3. package/dist/browser/jwe/flattened/decrypt.js +10 -5
  4. package/dist/browser/jwe/flattened/encrypt.js +5 -2
  5. package/dist/browser/jwk/embedded.js +2 -2
  6. package/dist/browser/jwk/from_key_like.js +2 -2
  7. package/dist/browser/jwk/parse.js +2 -31
  8. package/dist/browser/jwk/thumbprint.js +1 -1
  9. package/dist/browser/jwks/remote.js +2 -2
  10. package/dist/browser/jws/compact/verify.js +5 -1
  11. package/dist/browser/jws/flattened/sign.js +5 -2
  12. package/dist/browser/jws/flattened/verify.js +7 -2
  13. package/dist/browser/jwt/decrypt.js +5 -1
  14. package/dist/browser/jwt/unsecured.js +1 -1
  15. package/dist/browser/jwt/verify.js +5 -1
  16. package/dist/browser/key/export.js +12 -0
  17. package/dist/browser/key/import.js +119 -0
  18. package/dist/browser/lib/decrypt_key_management.js +4 -4
  19. package/dist/browser/lib/encrypt_key_management.js +3 -3
  20. package/dist/browser/lib/format_pem.js +4 -0
  21. package/dist/browser/runtime/aeskw.js +1 -1
  22. package/dist/browser/runtime/asn1.js +119 -0
  23. package/dist/browser/runtime/base64url.js +12 -7
  24. package/dist/browser/runtime/decrypt.js +1 -1
  25. package/dist/browser/runtime/encrypt.js +1 -1
  26. package/dist/browser/runtime/fetch_jwks.js +2 -2
  27. package/dist/browser/runtime/generate.js +18 -2
  28. package/dist/browser/runtime/global.js +17 -0
  29. package/dist/browser/runtime/jwk_to_key.js +29 -5
  30. package/dist/browser/runtime/sign.js +1 -1
  31. package/dist/browser/runtime/subtle_dsa.js +4 -1
  32. package/dist/browser/runtime/verify.js +1 -1
  33. package/dist/node/cjs/jwe/compact/decrypt.js +5 -1
  34. package/dist/node/cjs/jwe/flattened/decrypt.js +10 -5
  35. package/dist/node/cjs/jwe/flattened/encrypt.js +5 -2
  36. package/dist/node/cjs/jwk/embedded.js +2 -2
  37. package/dist/node/cjs/jwk/from_key_like.js +2 -2
  38. package/dist/node/cjs/jwk/parse.js +2 -31
  39. package/dist/node/cjs/jwk/thumbprint.js +1 -1
  40. package/dist/node/cjs/jwks/remote.js +2 -2
  41. package/dist/node/cjs/jws/compact/verify.js +5 -1
  42. package/dist/node/cjs/jws/flattened/sign.js +5 -2
  43. package/dist/node/cjs/jws/flattened/verify.js +7 -2
  44. package/dist/node/cjs/jwt/decrypt.js +5 -1
  45. package/dist/node/cjs/jwt/unsecured.js +1 -1
  46. package/dist/node/cjs/jwt/verify.js +5 -1
  47. package/dist/node/cjs/key/export.js +18 -0
  48. package/dist/node/cjs/key/import.js +126 -0
  49. package/dist/node/cjs/lib/decrypt_key_management.js +4 -4
  50. package/dist/node/cjs/lib/encrypt_key_management.js +3 -3
  51. package/dist/node/cjs/lib/format_pem.js +6 -0
  52. package/dist/node/cjs/runtime/aeskw.js +1 -1
  53. package/dist/node/cjs/runtime/asn1.js +46 -0
  54. package/dist/node/cjs/runtime/asn1_sequence_encoder.js +1 -1
  55. package/dist/node/cjs/runtime/base64url.js +5 -1
  56. package/dist/node/cjs/runtime/decrypt.js +1 -1
  57. package/dist/node/cjs/runtime/ecdhes.js +28 -16
  58. package/dist/node/cjs/runtime/encrypt.js +1 -1
  59. package/dist/node/cjs/runtime/generate.js +2 -2
  60. package/dist/node/cjs/runtime/get_named_curve.js +12 -8
  61. package/dist/node/cjs/runtime/is_key_object.js +3 -12
  62. package/dist/node/cjs/runtime/jwk_to_key.js +1 -1
  63. package/dist/node/cjs/runtime/key_to_jwk.js +3 -3
  64. package/dist/node/cjs/runtime/webcrypto.js +12 -18
  65. package/dist/node/esm/jwe/compact/decrypt.js +5 -1
  66. package/dist/node/esm/jwe/flattened/decrypt.js +10 -5
  67. package/dist/node/esm/jwe/flattened/encrypt.js +5 -2
  68. package/dist/node/esm/jwk/embedded.js +2 -2
  69. package/dist/node/esm/jwk/from_key_like.js +2 -2
  70. package/dist/node/esm/jwk/parse.js +2 -31
  71. package/dist/node/esm/jwk/thumbprint.js +1 -1
  72. package/dist/node/esm/jwks/remote.js +2 -2
  73. package/dist/node/esm/jws/compact/verify.js +5 -1
  74. package/dist/node/esm/jws/flattened/sign.js +5 -2
  75. package/dist/node/esm/jws/flattened/verify.js +7 -2
  76. package/dist/node/esm/jwt/decrypt.js +5 -1
  77. package/dist/node/esm/jwt/unsecured.js +1 -1
  78. package/dist/node/esm/jwt/verify.js +5 -1
  79. package/dist/node/esm/key/export.js +12 -0
  80. package/dist/node/esm/key/import.js +119 -0
  81. package/dist/node/esm/lib/decrypt_key_management.js +4 -4
  82. package/dist/node/esm/lib/encrypt_key_management.js +3 -3
  83. package/dist/node/esm/lib/format_pem.js +4 -0
  84. package/dist/node/esm/runtime/aeskw.js +1 -1
  85. package/dist/node/esm/runtime/asn1.js +39 -0
  86. package/dist/node/esm/runtime/asn1_sequence_encoder.js +1 -1
  87. package/dist/node/esm/runtime/base64url.js +2 -0
  88. package/dist/node/esm/runtime/decrypt.js +1 -1
  89. package/dist/node/esm/runtime/ecdhes.js +28 -16
  90. package/dist/node/esm/runtime/encrypt.js +1 -1
  91. package/dist/node/esm/runtime/generate.js +2 -2
  92. package/dist/node/esm/runtime/get_named_curve.js +12 -8
  93. package/dist/node/esm/runtime/is_key_object.js +3 -12
  94. package/dist/node/esm/runtime/jwk_to_key.js +1 -1
  95. package/dist/node/esm/runtime/key_to_jwk.js +3 -3
  96. package/dist/node/esm/runtime/webcrypto.js +12 -18
  97. package/dist/types/jwe/compact/decrypt.d.ts +3 -2
  98. package/dist/types/jwe/flattened/decrypt.d.ts +3 -2
  99. package/dist/types/jwe/general/decrypt.d.ts +3 -2
  100. package/dist/types/jws/compact/verify.d.ts +3 -2
  101. package/dist/types/jws/flattened/verify.d.ts +3 -2
  102. package/dist/types/jws/general/verify.d.ts +3 -2
  103. package/dist/types/jwt/decrypt.d.ts +3 -2
  104. package/dist/types/jwt/verify.d.ts +3 -2
  105. package/dist/types/key/export.d.ts +5 -0
  106. package/dist/types/key/import.d.ts +9 -0
  107. package/dist/types/types.d.ts +3 -0
  108. package/package.json +18 -115
@@ -3,7 +3,7 @@ import crypto, { isCryptoKey } from './webcrypto.js';
3
3
  import invalidKeyInput from './invalid_key_input.js';
4
4
  function checkKeySize(key, alg) {
5
5
  if (key.algorithm.length !== parseInt(alg.substr(1, 3), 10)) {
6
- throw new TypeError(`invalid key size for alg: ${alg}`);
6
+ throw new TypeError(`Invalid key size for alg: ${alg}`);
7
7
  }
8
8
  }
9
9
  function getCryptoKey(key, usage) {
@@ -0,0 +1,119 @@
1
+ import globalThis, { isCloudflareWorkers, isNodeJs } from './global.js';
2
+ import crypto, { isCryptoKey } from './webcrypto.js';
3
+ import invalidKeyInput from './invalid_key_input.js';
4
+ import { encodeBase64 } from './base64url.js';
5
+ import formatPEM from '../lib/format_pem.js';
6
+ import { JOSENotSupported } from '../util/errors.js';
7
+ const genericExport = async (keyType, keyFormat, key) => {
8
+ if (!isCryptoKey(key)) {
9
+ throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
10
+ }
11
+ if (!key.extractable) {
12
+ throw new TypeError('CryptoKey is not extractable');
13
+ }
14
+ if (key.type !== keyType) {
15
+ throw new TypeError(`key is not a ${keyType} key`);
16
+ }
17
+ return formatPEM(encodeBase64(new Uint8Array(await crypto.subtle.exportKey(keyFormat, key))), `${keyType.toUpperCase()} KEY`);
18
+ };
19
+ export const toSPKI = (key) => {
20
+ return genericExport('public', 'spki', key);
21
+ };
22
+ export const toPKCS8 = (key) => {
23
+ return genericExport('private', 'pkcs8', key);
24
+ };
25
+ const getNamedCurve = (keyData) => {
26
+ const keyDataStr = keyData.toString();
27
+ switch (true) {
28
+ case keyDataStr.includes(new Uint8Array([
29
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
30
+ 0x3d, 0x03, 0x01, 0x07,
31
+ ]).toString()):
32
+ return 'P-256';
33
+ case keyDataStr.includes(new Uint8Array([
34
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
35
+ 0x22,
36
+ ]).toString()):
37
+ return 'P-384';
38
+ case keyDataStr.includes(new Uint8Array([
39
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
40
+ 0x23,
41
+ ]).toString()):
42
+ return 'P-521';
43
+ case (isCloudflareWorkers() || isNodeJs()) &&
44
+ keyDataStr.includes(new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x70]).toString()):
45
+ return 'Ed25519';
46
+ case isNodeJs() &&
47
+ keyDataStr.includes(new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x71]).toString()):
48
+ return 'Ed448';
49
+ default:
50
+ throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type');
51
+ }
52
+ };
53
+ const genericImport = async (replace, keyFormat, pem, alg, options) => {
54
+ var _a;
55
+ let algorithm;
56
+ let keyUsages;
57
+ const keyData = new Uint8Array(globalThis
58
+ .atob(pem.replace(replace, ''))
59
+ .split('')
60
+ .map((c) => c.charCodeAt(0)));
61
+ const isPublic = keyFormat === 'spki';
62
+ switch (alg) {
63
+ case 'PS256':
64
+ case 'PS384':
65
+ case 'PS512':
66
+ algorithm = { name: 'RSA-PSS', hash: { name: `SHA-${alg.substr(-3)}` } };
67
+ keyUsages = isPublic ? ['verify'] : ['sign'];
68
+ break;
69
+ case 'RS256':
70
+ case 'RS384':
71
+ case 'RS512':
72
+ algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: { name: `SHA-${alg.substr(-3)}` } };
73
+ keyUsages = isPublic ? ['verify'] : ['sign'];
74
+ break;
75
+ case 'RSA-OAEP':
76
+ case 'RSA-OAEP-256':
77
+ case 'RSA-OAEP-384':
78
+ case 'RSA-OAEP-512':
79
+ algorithm = {
80
+ name: 'RSA-OAEP',
81
+ hash: { name: `SHA-${parseInt(alg.substr(-3), 10) || 1}` },
82
+ };
83
+ keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'];
84
+ break;
85
+ case 'ES256':
86
+ algorithm = { name: 'ECDSA', namedCurve: 'P-256' };
87
+ keyUsages = isPublic ? ['verify'] : ['sign'];
88
+ break;
89
+ case 'ES384':
90
+ algorithm = { name: 'ECDSA', namedCurve: 'P-384' };
91
+ keyUsages = isPublic ? ['verify'] : ['sign'];
92
+ break;
93
+ case 'ES512':
94
+ algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
95
+ keyUsages = isPublic ? ['verify'] : ['sign'];
96
+ break;
97
+ case 'ECDH-ES':
98
+ case 'ECDH-ES+A128KW':
99
+ case 'ECDH-ES+A192KW':
100
+ case 'ECDH-ES+A256KW':
101
+ algorithm = { name: 'ECDH', namedCurve: getNamedCurve(keyData) };
102
+ keyUsages = isPublic ? [] : ['deriveBits'];
103
+ break;
104
+ case (isCloudflareWorkers() || isNodeJs()) && 'EdDSA':
105
+ const namedCurve = getNamedCurve(keyData).toUpperCase();
106
+ algorithm = { name: `NODE-${namedCurve}`, namedCurve: `NODE-${namedCurve}` };
107
+ keyUsages = isPublic ? ['verify'] : ['sign'];
108
+ break;
109
+ default:
110
+ throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
111
+ }
112
+ return crypto.subtle.importKey(keyFormat, keyData, algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages);
113
+ };
114
+ export const fromPKCS8 = (pem, alg, options) => {
115
+ return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options);
116
+ };
117
+ export const fromSPKI = (pem, alg, options) => {
118
+ return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options);
119
+ };
@@ -1,6 +1,6 @@
1
1
  import { encoder, decoder } from '../lib/buffer_utils.js';
2
2
  import globalThis from './global.js';
3
- export const encode = (input) => {
3
+ export const encodeBase64 = (input) => {
4
4
  let unencoded = input;
5
5
  if (typeof unencoded === 'string') {
6
6
  unencoded = encoder.encode(unencoded);
@@ -10,8 +10,16 @@ export const encode = (input) => {
10
10
  for (let i = 0; i < unencoded.length; i += CHUNK_SIZE) {
11
11
  arr.push(String.fromCharCode.apply(null, unencoded.subarray(i, i + CHUNK_SIZE)));
12
12
  }
13
- const base64string = globalThis.btoa(arr.join(''));
14
- return base64string.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
13
+ return globalThis.btoa(arr.join(''));
14
+ };
15
+ export const encode = (input) => {
16
+ return encodeBase64(input).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
17
+ };
18
+ export const decodeBase64 = (encoded) => {
19
+ return new Uint8Array(globalThis
20
+ .atob(encoded)
21
+ .split('')
22
+ .map((c) => c.charCodeAt(0)));
15
23
  };
16
24
  export const decode = (input) => {
17
25
  let encoded = input;
@@ -20,10 +28,7 @@ export const decode = (input) => {
20
28
  }
21
29
  encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
22
30
  try {
23
- return new Uint8Array(globalThis
24
- .atob(encoded)
25
- .split('')
26
- .map((c) => c.charCodeAt(0)));
31
+ return decodeBase64(encoded);
27
32
  }
28
33
  catch (_a) {
29
34
  throw new TypeError('The input to be decoded is not correctly encoded.');
@@ -66,7 +66,7 @@ const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
66
66
  case 'A256GCM':
67
67
  return gcmDecrypt(cek, ciphertext, iv, tag, aad);
68
68
  default:
69
- throw new JOSENotSupported('unsupported JWE Content Encryption Algorithm');
69
+ throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
70
70
  }
71
71
  };
72
72
  export default decrypt;
@@ -49,7 +49,7 @@ const encrypt = async (enc, plaintext, cek, iv, aad) => {
49
49
  case 'A256GCM':
50
50
  return gcmEncrypt(plaintext, cek, iv, aad);
51
51
  default:
52
- throw new JOSENotSupported('unsupported JWE Content Encryption Algorithm');
52
+ throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
53
53
  }
54
54
  };
55
55
  export default encrypt;
@@ -1,5 +1,5 @@
1
1
  import { JOSEError } from '../util/errors.js';
2
- import globalThis from './global.js';
2
+ import globalThis, { isCloudflareWorkers } from './global.js';
3
3
  const fetchJwks = async (url, timeout) => {
4
4
  let controller;
5
5
  if (typeof AbortController === 'function') {
@@ -10,7 +10,7 @@ const fetchJwks = async (url, timeout) => {
10
10
  signal: controller ? controller.signal : undefined,
11
11
  redirect: 'manual',
12
12
  method: 'GET',
13
- ...(typeof globalThis.WebSocketPair === 'undefined'
13
+ ...(!isCloudflareWorkers()
14
14
  ? {
15
15
  referrerPolicy: 'no-referrer',
16
16
  credentials: 'omit',
@@ -1,3 +1,4 @@
1
+ import { isCloudflareWorkers, isNodeJs } from './global.js';
1
2
  import crypto from './webcrypto.js';
2
3
  import { JOSENotSupported } from '../util/errors.js';
3
4
  import random from './random.js';
@@ -37,7 +38,7 @@ export async function generateSecret(alg, options) {
37
38
  keyUsages = ['encrypt', 'decrypt'];
38
39
  break;
39
40
  default:
40
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
41
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
41
42
  }
42
43
  return crypto.subtle.generateKey(algorithm, (_a = options === null || options === void 0 ? void 0 : options.extractable) !== null && _a !== void 0 ? _a : false, keyUsages);
43
44
  }
@@ -100,6 +101,21 @@ export async function generateKeyPair(alg, options) {
100
101
  algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
101
102
  keyUsages = ['sign', 'verify'];
102
103
  break;
104
+ case (isCloudflareWorkers() || isNodeJs()) && 'EdDSA':
105
+ switch (options === null || options === void 0 ? void 0 : options.crv) {
106
+ case undefined:
107
+ case 'Ed25519':
108
+ algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' };
109
+ keyUsages = ['sign', 'verify'];
110
+ break;
111
+ case isNodeJs() && 'Ed448':
112
+ algorithm = { name: 'NODE-ED448', namedCurve: 'NODE-ED448' };
113
+ keyUsages = ['sign', 'verify'];
114
+ break;
115
+ default:
116
+ throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are Ed25519 and Ed448');
117
+ }
118
+ break;
103
119
  case 'ECDH-ES':
104
120
  case 'ECDH-ES+A128KW':
105
121
  case 'ECDH-ES+A192KW':
@@ -108,7 +124,7 @@ export async function generateKeyPair(alg, options) {
108
124
  keyUsages = ['deriveKey', 'deriveBits'];
109
125
  break;
110
126
  default:
111
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
127
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
112
128
  }
113
129
  return (crypto.subtle.generateKey(algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages));
114
130
  }
@@ -8,3 +8,20 @@ function getGlobal() {
8
8
  throw new Error('unable to locate global object');
9
9
  }
10
10
  export default getGlobal();
11
+ export function isCloudflareWorkers() {
12
+ try {
13
+ return getGlobal().WebSocketPair !== undefined;
14
+ }
15
+ catch (_a) {
16
+ return false;
17
+ }
18
+ }
19
+ export function isNodeJs() {
20
+ var _a, _b;
21
+ try {
22
+ return ((_b = (_a = getGlobal().process) === null || _a === void 0 ? void 0 : _a.versions) === null || _b === void 0 ? void 0 : _b.node) !== undefined;
23
+ }
24
+ catch (_c) {
25
+ return false;
26
+ }
27
+ }
@@ -1,3 +1,4 @@
1
+ import { isCloudflareWorkers, isNodeJs } from './global.js';
1
2
  import crypto from './webcrypto.js';
2
3
  import { JOSENotSupported } from '../util/errors.js';
3
4
  import { decode as base64url } from './base64url.js';
@@ -39,7 +40,7 @@ function subtleMapping(jwk) {
39
40
  keyUsages = ['deriveBits'];
40
41
  break;
41
42
  default:
42
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
43
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
43
44
  }
44
45
  break;
45
46
  }
@@ -68,16 +69,22 @@ function subtleMapping(jwk) {
68
69
  keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];
69
70
  break;
70
71
  default:
71
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
72
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
72
73
  }
73
74
  break;
74
75
  }
75
76
  case 'EC': {
76
77
  switch (jwk.alg) {
77
78
  case 'ES256':
79
+ algorithm = { name: 'ECDSA', namedCurve: 'P-256' };
80
+ keyUsages = jwk.d ? ['sign'] : ['verify'];
81
+ break;
78
82
  case 'ES384':
83
+ algorithm = { name: 'ECDSA', namedCurve: 'P-384' };
84
+ keyUsages = jwk.d ? ['sign'] : ['verify'];
85
+ break;
79
86
  case 'ES512':
80
- algorithm = { name: 'ECDSA', namedCurve: jwk.crv };
87
+ algorithm = { name: 'ECDSA', namedCurve: 'P-521' };
81
88
  keyUsages = jwk.d ? ['sign'] : ['verify'];
82
89
  break;
83
90
  case 'ECDH-ES':
@@ -88,12 +95,29 @@ function subtleMapping(jwk) {
88
95
  keyUsages = jwk.d ? ['deriveBits'] : [];
89
96
  break;
90
97
  default:
91
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
98
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
92
99
  }
93
100
  break;
94
101
  }
102
+ case (isCloudflareWorkers() || isNodeJs()) && 'OKP':
103
+ if (jwk.alg !== 'EdDSA') {
104
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
105
+ }
106
+ switch (jwk.crv) {
107
+ case 'Ed25519':
108
+ algorithm = { name: 'NODE-ED25519', namedCurve: 'NODE-ED25519' };
109
+ keyUsages = jwk.d ? ['sign'] : ['verify'];
110
+ break;
111
+ case isNodeJs() && 'Ed448':
112
+ algorithm = { name: 'NODE-ED448', namedCurve: 'NODE-ED448' };
113
+ keyUsages = jwk.d ? ['sign'] : ['verify'];
114
+ break;
115
+ default:
116
+ throw new JOSENotSupported('Invalid or unsupported JWK "crv" (Subtype of Key Pair) Parameter value');
117
+ }
118
+ break;
95
119
  default:
96
- throw new JOSENotSupported('unsupported or invalid JWK "kty" (Key Type) Parameter value');
120
+ throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
97
121
  }
98
122
  return { algorithm, keyUsages };
99
123
  }
@@ -5,7 +5,7 @@ import getSignKey from './get_sign_verify_key.js';
5
5
  const sign = async (alg, key, data) => {
6
6
  const cryptoKey = await getSignKey(alg, key, 'sign');
7
7
  checkKeyLength(alg, cryptoKey);
8
- const signature = await crypto.subtle.sign(subtleAlgorithm(alg), cryptoKey, data);
8
+ const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm.namedCurve), cryptoKey, data);
9
9
  return new Uint8Array(signature);
10
10
  };
11
11
  export default sign;
@@ -1,5 +1,6 @@
1
+ import { isCloudflareWorkers, isNodeJs } from './global.js';
1
2
  import { JOSENotSupported } from '../util/errors.js';
2
- export default function subtleDsa(alg) {
3
+ export default function subtleDsa(alg, crv) {
3
4
  switch (alg) {
4
5
  case 'HS256':
5
6
  return { hash: { name: 'SHA-256' }, name: 'HMAC' };
@@ -37,6 +38,8 @@ export default function subtleDsa(alg) {
37
38
  return { hash: { name: 'SHA-384' }, name: 'ECDSA', namedCurve: 'P-384' };
38
39
  case 'ES512':
39
40
  return { hash: { name: 'SHA-512' }, name: 'ECDSA', namedCurve: 'P-521' };
41
+ case (isCloudflareWorkers() || isNodeJs()) && 'EdDSA':
42
+ return { name: crv, namedCurve: crv };
40
43
  default:
41
44
  throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
42
45
  }
@@ -5,7 +5,7 @@ import getVerifyKey from './get_sign_verify_key.js';
5
5
  const verify = async (alg, key, signature, data) => {
6
6
  const cryptoKey = await getVerifyKey(alg, key, 'verify');
7
7
  checkKeyLength(alg, cryptoKey);
8
- const algorithm = subtleAlgorithm(alg);
8
+ const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm.namedCurve);
9
9
  try {
10
10
  return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
11
11
  }
@@ -22,7 +22,11 @@ async function compactDecrypt(jwe, key, options) {
22
22
  tag: (tag || undefined),
23
23
  encrypted_key: encryptedKey || undefined,
24
24
  }, key, options);
25
- return { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
25
+ const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
26
+ if (typeof key === 'function') {
27
+ return { ...result, key: decrypted.key };
28
+ }
29
+ return result;
26
30
  }
27
31
  exports.compactDecrypt = compactDecrypt;
28
32
  exports.default = compactDecrypt;
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.flattenedDecrypt = void 0;
4
- const errors_js_1 = require("../../util/errors.js");
5
- const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
6
- const is_object_js_1 = require("../../lib/is_object.js");
7
4
  const base64url_js_1 = require("../../runtime/base64url.js");
8
5
  const decrypt_js_1 = require("../../runtime/decrypt.js");
9
6
  const zlib_js_1 = require("../../runtime/zlib.js");
7
+ const random_js_1 = require("../../runtime/random.js");
8
+ const errors_js_1 = require("../../util/errors.js");
9
+ const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
10
+ const is_object_js_1 = require("../../lib/is_object.js");
10
11
  const decrypt_key_management_js_1 = require("../../lib/decrypt_key_management.js");
11
12
  const buffer_utils_js_1 = require("../../lib/buffer_utils.js");
12
13
  const cek_js_1 = require("../../lib/cek.js");
13
- const random_js_1 = require("../../runtime/random.js");
14
14
  const validate_crit_js_1 = require("../../lib/validate_crit.js");
15
15
  const validate_algorithms_js_1 = require("../../lib/validate_algorithms.js");
16
16
  const generateCek = (0, cek_js_1.default)(random_js_1.default);
@@ -73,7 +73,7 @@ async function flattenedDecrypt(jwe, key, options) {
73
73
  throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
74
74
  }
75
75
  if (joseHeader.zip !== 'DEF') {
76
- throw new errors_js_1.JOSENotSupported('unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
76
+ throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
77
77
  }
78
78
  }
79
79
  const { alg, enc } = joseHeader;
@@ -95,8 +95,10 @@ async function flattenedDecrypt(jwe, key, options) {
95
95
  if (jwe.encrypted_key !== undefined) {
96
96
  encryptedKey = (0, base64url_js_1.decode)(jwe.encrypted_key);
97
97
  }
98
+ let resolvedKey = false;
98
99
  if (typeof key === 'function') {
99
100
  key = await key(parsedProt, jwe);
101
+ resolvedKey = true;
100
102
  }
101
103
  let cek;
102
104
  try {
@@ -135,6 +137,9 @@ async function flattenedDecrypt(jwe, key, options) {
135
137
  if (jwe.header !== undefined) {
136
138
  result.unprotectedHeader = jwe.header;
137
139
  }
140
+ if (resolvedKey) {
141
+ return { ...result, key };
142
+ }
138
143
  return result;
139
144
  }
140
145
  exports.flattenedDecrypt = flattenedDecrypt;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlattenedEncrypt = void 0;
4
- const iv_js_1 = require("../../lib/iv.js");
5
4
  const base64url_js_1 = require("../../runtime/base64url.js");
6
5
  const random_js_1 = require("../../runtime/random.js");
7
6
  const encrypt_js_1 = require("../../runtime/encrypt.js");
8
7
  const zlib_js_1 = require("../../runtime/zlib.js");
8
+ const iv_js_1 = require("../../lib/iv.js");
9
9
  const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js");
10
10
  const errors_js_1 = require("../../util/errors.js");
11
11
  const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
@@ -15,6 +15,9 @@ const generateIv = (0, iv_js_1.default)(random_js_1.default);
15
15
  const checkExtensions = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map());
16
16
  class FlattenedEncrypt {
17
17
  constructor(plaintext) {
18
+ if (!(plaintext instanceof Uint8Array)) {
19
+ throw new TypeError('plaintext must be an instance of Uint8Array');
20
+ }
18
21
  this._plaintext = plaintext;
19
22
  }
20
23
  setKeyManagementParameters(parameters) {
@@ -81,7 +84,7 @@ class FlattenedEncrypt {
81
84
  throw new errors_js_1.JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
82
85
  }
83
86
  if (joseHeader.zip !== 'DEF') {
84
- throw new errors_js_1.JOSENotSupported('unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
87
+ throw new errors_js_1.JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
85
88
  }
86
89
  }
87
90
  const { alg, enc } = joseHeader;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmbeddedJWK = void 0;
4
- const parse_js_1 = require("./parse.js");
4
+ const import_js_1 = require("../key/import.js");
5
5
  const is_object_js_1 = require("../lib/is_object.js");
6
6
  const errors_js_1 = require("../util/errors.js");
7
7
  async function EmbeddedJWK(protectedHeader, token) {
@@ -12,7 +12,7 @@ async function EmbeddedJWK(protectedHeader, token) {
12
12
  if (!(0, is_object_js_1.default)(joseHeader.jwk)) {
13
13
  throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object');
14
14
  }
15
- const key = await (0, parse_js_1.default)(joseHeader.jwk, joseHeader.alg, true);
15
+ const key = (await (0, import_js_1.importJWK)({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true));
16
16
  if (key.type !== 'public') {
17
17
  throw new errors_js_1.JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');
18
18
  }
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fromKeyLike = void 0;
4
- const key_to_jwk_js_1 = require("../runtime/key_to_jwk.js");
4
+ const export_js_1 = require("../key/export.js");
5
5
  async function fromKeyLike(key) {
6
- return (0, key_to_jwk_js_1.default)(key);
6
+ return (0, export_js_1.exportJWK)(key);
7
7
  }
8
8
  exports.fromKeyLike = fromKeyLike;
9
9
  exports.default = fromKeyLike;
@@ -1,38 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseJwk = void 0;
4
- const base64url_js_1 = require("../runtime/base64url.js");
5
- const jwk_to_key_js_1 = require("../runtime/jwk_to_key.js");
6
- const errors_js_1 = require("../util/errors.js");
7
- const is_object_js_1 = require("../lib/is_object.js");
4
+ const import_js_1 = require("../key/import.js");
8
5
  async function parseJwk(jwk, alg, octAsKeyObject) {
9
- if (!(0, is_object_js_1.default)(jwk)) {
10
- throw new TypeError('JWK must be an object');
11
- }
12
- alg || (alg = jwk.alg);
13
- if (typeof alg !== 'string' || !alg) {
14
- throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
15
- }
16
- switch (jwk.kty) {
17
- case 'oct':
18
- if (typeof jwk.k !== 'string' || !jwk.k) {
19
- throw new TypeError('missing "k" (Key Value) Parameter value');
20
- }
21
- octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true);
22
- if (octAsKeyObject) {
23
- return (0, jwk_to_key_js_1.default)({ ...jwk, alg, ext: false });
24
- }
25
- return (0, base64url_js_1.decode)(jwk.k);
26
- case 'RSA':
27
- if (jwk.oth !== undefined) {
28
- throw new errors_js_1.JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
29
- }
30
- case 'EC':
31
- case 'OKP':
32
- return (0, jwk_to_key_js_1.default)({ ...jwk, alg });
33
- default:
34
- throw new errors_js_1.JOSENotSupported('unsupported "kty" (Key Type) Parameter value');
35
- }
6
+ return (0, import_js_1.importJWK)(jwk, alg, octAsKeyObject);
36
7
  }
37
8
  exports.parseJwk = parseJwk;
38
9
  exports.default = parseJwk;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateThumbprint = void 0;
4
- const errors_js_1 = require("../util/errors.js");
5
4
  const digest_js_1 = require("../runtime/digest.js");
6
5
  const base64url_js_1 = require("../runtime/base64url.js");
6
+ const errors_js_1 = require("../util/errors.js");
7
7
  const buffer_utils_js_1 = require("../lib/buffer_utils.js");
8
8
  const is_object_js_1 = require("../lib/is_object.js");
9
9
  const check = (value, description) => {
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createRemoteJWKSet = void 0;
4
+ const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js");
4
5
  const parse_js_1 = require("../jwk/parse.js");
5
6
  const errors_js_1 = require("../util/errors.js");
6
- const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js");
7
7
  const is_object_js_1 = require("../lib/is_object.js");
8
8
  function getKtyFromAlg(alg) {
9
9
  switch (alg.substr(0, 2)) {
@@ -96,7 +96,7 @@ class RemoteJWKSet {
96
96
  }
97
97
  const cached = this._cached.get(jwk);
98
98
  if (cached[protectedHeader.alg] === undefined) {
99
- const keyObject = await (0, parse_js_1.default)({ ...jwk, alg: protectedHeader.alg });
99
+ const keyObject = (await (0, parse_js_1.default)({ ...jwk, alg: protectedHeader.alg, ext: true }));
100
100
  if (keyObject.type !== 'public') {
101
101
  throw new errors_js_1.JWKSInvalid('JSON Web Key Set members must be public keys');
102
102
  }
@@ -20,7 +20,11 @@ async function compactVerify(jws, key, options) {
20
20
  protected: protectedHeader || undefined,
21
21
  signature: (signature || undefined),
22
22
  }, key, options);
23
- return { payload: verified.payload, protectedHeader: verified.protectedHeader };
23
+ const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };
24
+ if (typeof key === 'function') {
25
+ return { ...result, key: verified.key };
26
+ }
27
+ return result;
24
28
  }
25
29
  exports.compactVerify = compactVerify;
26
30
  exports.default = compactVerify;
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlattenedSign = void 0;
4
+ const base64url_js_1 = require("../../runtime/base64url.js");
5
+ const sign_js_1 = require("../../runtime/sign.js");
4
6
  const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
5
7
  const errors_js_1 = require("../../util/errors.js");
6
8
  const buffer_utils_js_1 = require("../../lib/buffer_utils.js");
7
- const base64url_js_1 = require("../../runtime/base64url.js");
8
- const sign_js_1 = require("../../runtime/sign.js");
9
9
  const check_key_type_js_1 = require("../../lib/check_key_type.js");
10
10
  const validate_crit_js_1 = require("../../lib/validate_crit.js");
11
11
  const checkExtensions = validate_crit_js_1.default.bind(undefined, errors_js_1.JWSInvalid, new Map([['b64', true]]));
12
12
  class FlattenedSign {
13
13
  constructor(payload) {
14
+ if (!(payload instanceof Uint8Array)) {
15
+ throw new TypeError('payload must be an instance of Uint8Array');
16
+ }
14
17
  this._payload = payload;
15
18
  }
16
19
  setProtectedHeader(protectedHeader) {