jose 4.0.3 → 4.1.2

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 (70) hide show
  1. package/dist/browser/{runtime → lib}/aesgcmkw.js +8 -8
  2. package/dist/browser/lib/cek.js +18 -16
  3. package/dist/browser/lib/check_iv_length.js +2 -2
  4. package/dist/browser/lib/check_key_type.js +1 -1
  5. package/dist/browser/lib/crypto_key.js +150 -0
  6. package/dist/browser/lib/decrypt_key_management.js +3 -3
  7. package/dist/browser/lib/encrypt_key_management.js +3 -3
  8. package/dist/browser/{runtime → lib}/invalid_key_input.js +0 -0
  9. package/dist/browser/lib/iv.js +24 -19
  10. package/dist/browser/runtime/aeskw.js +4 -3
  11. package/dist/browser/runtime/asn1.js +4 -4
  12. package/dist/browser/runtime/bogus.js +1 -1
  13. package/dist/browser/runtime/check_cek_length.js +7 -0
  14. package/dist/browser/runtime/decrypt.js +10 -4
  15. package/dist/browser/runtime/ecdhes.js +5 -4
  16. package/dist/browser/runtime/encrypt.js +10 -4
  17. package/dist/browser/runtime/generate.js +4 -4
  18. package/dist/browser/runtime/get_sign_verify_key.js +5 -4
  19. package/dist/browser/runtime/jwk_to_key.js +4 -4
  20. package/dist/browser/runtime/key_to_jwk.js +1 -1
  21. package/dist/browser/runtime/pbes2kw.js +14 -36
  22. package/dist/browser/runtime/rsaes.js +5 -4
  23. package/dist/browser/runtime/subtle_dsa.js +7 -26
  24. package/dist/browser/runtime/webcrypto.js +0 -145
  25. package/dist/node/cjs/{runtime → lib}/aesgcmkw.js +8 -8
  26. package/dist/node/cjs/lib/cek.js +20 -17
  27. package/dist/node/cjs/lib/check_iv_length.js +1 -1
  28. package/dist/node/cjs/lib/check_key_type.js +1 -1
  29. package/dist/node/cjs/lib/crypto_key.js +155 -0
  30. package/dist/node/cjs/lib/decrypt_key_management.js +2 -2
  31. package/dist/node/cjs/lib/encrypt_key_management.js +2 -2
  32. package/dist/node/cjs/{runtime → lib}/invalid_key_input.js +0 -11
  33. package/dist/node/cjs/lib/iv.js +26 -20
  34. package/dist/node/cjs/runtime/aeskw.js +4 -2
  35. package/dist/node/cjs/runtime/asn1.js +2 -2
  36. package/dist/node/cjs/runtime/decrypt.js +4 -2
  37. package/dist/node/cjs/runtime/ecdhes.js +7 -4
  38. package/dist/node/cjs/runtime/encrypt.js +4 -2
  39. package/dist/node/cjs/runtime/get_named_curve.js +2 -2
  40. package/dist/node/cjs/runtime/get_sign_verify_key.js +6 -4
  41. package/dist/node/cjs/runtime/global.js +11 -0
  42. package/dist/node/cjs/runtime/key_to_jwk.js +2 -2
  43. package/dist/node/cjs/runtime/node_key.js +6 -10
  44. package/dist/node/cjs/runtime/pbes2kw.js +4 -2
  45. package/dist/node/cjs/runtime/rsaes.js +4 -2
  46. package/dist/node/cjs/runtime/webcrypto.js +1 -152
  47. package/dist/node/esm/{runtime → lib}/aesgcmkw.js +8 -8
  48. package/dist/node/esm/lib/cek.js +18 -16
  49. package/dist/node/esm/lib/check_iv_length.js +2 -2
  50. package/dist/node/esm/lib/check_key_type.js +1 -1
  51. package/dist/node/esm/lib/crypto_key.js +150 -0
  52. package/dist/node/esm/lib/decrypt_key_management.js +3 -3
  53. package/dist/node/esm/lib/encrypt_key_management.js +3 -3
  54. package/dist/node/esm/{runtime → lib}/invalid_key_input.js +0 -11
  55. package/dist/node/esm/lib/iv.js +24 -19
  56. package/dist/node/esm/runtime/aeskw.js +6 -4
  57. package/dist/node/esm/runtime/asn1.js +4 -4
  58. package/dist/node/esm/runtime/decrypt.js +6 -4
  59. package/dist/node/esm/runtime/ecdhes.js +9 -6
  60. package/dist/node/esm/runtime/encrypt.js +6 -4
  61. package/dist/node/esm/runtime/get_named_curve.js +4 -4
  62. package/dist/node/esm/runtime/get_sign_verify_key.js +7 -5
  63. package/dist/node/esm/runtime/global.js +6 -0
  64. package/dist/node/esm/runtime/key_to_jwk.js +4 -4
  65. package/dist/node/esm/runtime/node_key.js +6 -10
  66. package/dist/node/esm/runtime/pbes2kw.js +6 -4
  67. package/dist/node/esm/runtime/rsaes.js +6 -4
  68. package/dist/node/esm/runtime/webcrypto.js +0 -149
  69. package/dist/types/jwks/remote.d.ts +4 -0
  70. package/package.json +4 -1
@@ -1,14 +1,14 @@
1
- import encrypt from './encrypt.js';
2
- import decrypt from './decrypt.js';
3
- import generateIv from '../lib/iv.js';
4
- import { encode as base64url } from './base64url.js';
5
- export const wrap = async (alg, key, cek, iv) => {
1
+ import encrypt from '../runtime/encrypt.js';
2
+ import decrypt from '../runtime/decrypt.js';
3
+ import generateIv from './iv.js';
4
+ import { encode as base64url } from '../runtime/base64url.js';
5
+ export async function wrap(alg, key, cek, iv) {
6
6
  const jweAlgorithm = alg.substr(0, 7);
7
7
  iv || (iv = generateIv(jweAlgorithm));
8
8
  const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
9
9
  return { encryptedKey, iv: base64url(iv), tag: base64url(tag) };
10
- };
11
- export const unwrap = async (alg, key, encryptedKey, iv, tag) => {
10
+ }
11
+ export async function unwrap(alg, key, encryptedKey, iv, tag) {
12
12
  const jweAlgorithm = alg.substr(0, 7);
13
13
  return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
14
- };
14
+ }
@@ -1,19 +1,21 @@
1
1
  import { JOSENotSupported } from '../util/errors.js';
2
2
  import random from '../runtime/random.js';
3
- const bitLengths = new Map([
4
- ['A128CBC-HS256', 256],
5
- ['A128GCM', 128],
6
- ['A192CBC-HS384', 384],
7
- ['A192GCM', 192],
8
- ['A256CBC-HS512', 512],
9
- ['A256GCM', 256],
10
- ]);
11
- const generateCek = (alg) => {
12
- const bitLength = bitLengths.get(alg);
13
- if (!bitLength) {
14
- throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
3
+ export function bitLength(alg) {
4
+ switch (alg) {
5
+ case 'A128CBC-HS256':
6
+ return 256;
7
+ case 'A192CBC-HS384':
8
+ return 384;
9
+ case 'A256CBC-HS512':
10
+ return 512;
11
+ case 'A128GCM':
12
+ return 128;
13
+ case 'A192GCM':
14
+ return 192;
15
+ case 'A256GCM':
16
+ return 256;
17
+ default:
18
+ throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
15
19
  }
16
- return random(new Uint8Array(bitLength >> 3));
17
- };
18
- export default generateCek;
19
- export { bitLengths };
20
+ }
21
+ export default (alg) => random(new Uint8Array(bitLength(alg) >> 3));
@@ -1,7 +1,7 @@
1
1
  import { JWEInvalid } from '../util/errors.js';
2
- import { bitLengths } from './iv.js';
2
+ import { bitLength } from './iv.js';
3
3
  const checkIvLength = (enc, iv) => {
4
- if (iv.length << 3 !== bitLengths.get(enc)) {
4
+ if (iv.length << 3 !== bitLength(enc)) {
5
5
  throw new JWEInvalid('Invalid Initialization Vector length');
6
6
  }
7
7
  };
@@ -1,4 +1,4 @@
1
- import invalidKeyInput from '../runtime/invalid_key_input.js';
1
+ import invalidKeyInput from './invalid_key_input.js';
2
2
  import isKeyLike, { types } from '../runtime/is_key_like.js';
3
3
  const symmetricTypeCheck = (key) => {
4
4
  if (key instanceof Uint8Array)
@@ -0,0 +1,150 @@
1
+ import { isCloudflareWorkers, isNodeJs } from '../runtime/global.js';
2
+ function unusable(name, prop = 'algorithm.name') {
3
+ return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
4
+ }
5
+ function isAlgorithm(algorithm, name) {
6
+ return algorithm.name === name;
7
+ }
8
+ function getHashLength(hash) {
9
+ return parseInt(hash.name.substr(4), 10);
10
+ }
11
+ function getNamedCurve(alg) {
12
+ switch (alg) {
13
+ case 'ES256':
14
+ return 'P-256';
15
+ case 'ES384':
16
+ return 'P-384';
17
+ case 'ES512':
18
+ return 'P-521';
19
+ default:
20
+ throw new Error('unreachable');
21
+ }
22
+ }
23
+ function checkUsage(key, usages) {
24
+ if (usages.length && !usages.some((expected) => key.usages.includes(expected))) {
25
+ let msg = 'CryptoKey does not support this operation, its usages must include ';
26
+ if (usages.length > 2) {
27
+ const last = usages.pop();
28
+ msg += `one of ${usages.join(', ')}, or ${last}.`;
29
+ }
30
+ else if (usages.length === 2) {
31
+ msg += `one of ${usages[0]} or ${usages[1]}.`;
32
+ }
33
+ else {
34
+ msg += `${usages[0]}.`;
35
+ }
36
+ throw new TypeError(msg);
37
+ }
38
+ }
39
+ export function checkSigCryptoKey(key, alg, ...usages) {
40
+ switch (alg) {
41
+ case 'HS256':
42
+ case 'HS384':
43
+ case 'HS512': {
44
+ if (!isAlgorithm(key.algorithm, 'HMAC'))
45
+ throw unusable('HMAC');
46
+ const expected = parseInt(alg.substr(2), 10);
47
+ const actual = getHashLength(key.algorithm.hash);
48
+ if (actual !== expected)
49
+ throw unusable(`SHA-${expected}`, 'algorithm.hash');
50
+ break;
51
+ }
52
+ case 'RS256':
53
+ case 'RS384':
54
+ case 'RS512': {
55
+ if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
56
+ throw unusable('RSASSA-PKCS1-v1_5');
57
+ const expected = parseInt(alg.substr(2), 10);
58
+ const actual = getHashLength(key.algorithm.hash);
59
+ if (actual !== expected)
60
+ throw unusable(`SHA-${expected}`, 'algorithm.hash');
61
+ break;
62
+ }
63
+ case 'PS256':
64
+ case 'PS384':
65
+ case 'PS512': {
66
+ if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
67
+ throw unusable('RSA-PSS');
68
+ const expected = parseInt(alg.substr(2), 10);
69
+ const actual = getHashLength(key.algorithm.hash);
70
+ if (actual !== expected)
71
+ throw unusable(`SHA-${expected}`, 'algorithm.hash');
72
+ break;
73
+ }
74
+ case isNodeJs() && 'EdDSA': {
75
+ if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448')
76
+ throw unusable('NODE-ED25519 or NODE-ED448');
77
+ break;
78
+ }
79
+ case isCloudflareWorkers() && 'EdDSA': {
80
+ if (!isAlgorithm(key.algorithm, 'NODE-ED25519'))
81
+ throw unusable('NODE-ED25519');
82
+ break;
83
+ }
84
+ case 'ES256':
85
+ case 'ES384':
86
+ case 'ES512': {
87
+ if (!isAlgorithm(key.algorithm, 'ECDSA'))
88
+ throw unusable('ECDSA');
89
+ const expected = getNamedCurve(alg);
90
+ const actual = key.algorithm.namedCurve;
91
+ if (actual !== expected)
92
+ throw unusable(expected, 'algorithm.namedCurve');
93
+ break;
94
+ }
95
+ default:
96
+ throw new TypeError('CryptoKey does not support this operation');
97
+ }
98
+ checkUsage(key, usages);
99
+ }
100
+ export function checkEncCryptoKey(key, alg, ...usages) {
101
+ switch (alg) {
102
+ case 'A128GCM':
103
+ case 'A192GCM':
104
+ case 'A256GCM': {
105
+ if (!isAlgorithm(key.algorithm, 'AES-GCM'))
106
+ throw unusable('AES-GCM');
107
+ const expected = parseInt(alg.substr(1, 3), 10);
108
+ const actual = key.algorithm.length;
109
+ if (actual !== expected)
110
+ throw unusable(expected, 'algorithm.length');
111
+ break;
112
+ }
113
+ case 'A128KW':
114
+ case 'A192KW':
115
+ case 'A256KW': {
116
+ if (!isAlgorithm(key.algorithm, 'AES-KW'))
117
+ throw unusable('AES-KW');
118
+ const expected = parseInt(alg.substr(1, 3), 10);
119
+ const actual = key.algorithm.length;
120
+ if (actual !== expected)
121
+ throw unusable(expected, 'algorithm.length');
122
+ break;
123
+ }
124
+ case 'ECDH-ES':
125
+ if (!isAlgorithm(key.algorithm, 'ECDH'))
126
+ throw unusable('ECDH');
127
+ break;
128
+ case 'PBES2-HS256+A128KW':
129
+ case 'PBES2-HS384+A192KW':
130
+ case 'PBES2-HS512+A256KW':
131
+ if (!isAlgorithm(key.algorithm, 'PBKDF2'))
132
+ throw unusable('PBKDF2');
133
+ break;
134
+ case 'RSA-OAEP':
135
+ case 'RSA-OAEP-256':
136
+ case 'RSA-OAEP-384':
137
+ case 'RSA-OAEP-512': {
138
+ if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
139
+ throw unusable('RSA-OAEP');
140
+ const expected = parseInt(alg.substr(9), 10) || 1;
141
+ const actual = getHashLength(key.algorithm.hash);
142
+ if (actual !== expected)
143
+ throw unusable(`SHA-${expected}`, 'algorithm.hash');
144
+ break;
145
+ }
146
+ default:
147
+ throw new TypeError('CryptoKey does not support this operation');
148
+ }
149
+ checkUsage(key, usages);
150
+ }
@@ -2,13 +2,13 @@ import { unwrap as aesKw } from '../runtime/aeskw.js';
2
2
  import * as ECDH from '../runtime/ecdhes.js';
3
3
  import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js';
4
4
  import { decrypt as rsaEs } from '../runtime/rsaes.js';
5
- import { unwrap as aesGcmKw } from '../runtime/aesgcmkw.js';
6
5
  import { decode as base64url } from '../runtime/base64url.js';
7
6
  import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
8
- import { bitLengths as cekLengths } from '../lib/cek.js';
7
+ import { bitLength as cekLength } from '../lib/cek.js';
9
8
  import { importJWK } from '../key/import.js';
10
9
  import checkKeyType from './check_key_type.js';
11
10
  import isObject from './is_object.js';
11
+ import { unwrap as aesGcmKw } from './aesgcmkw.js';
12
12
  async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
13
13
  checkKeyType(alg, key, 'decrypt');
14
14
  switch (alg) {
@@ -40,7 +40,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
40
40
  throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
41
41
  partyVInfo = base64url(joseHeader.apv);
42
42
  }
43
- const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, parseInt(alg.substr(-5, 3), 10) || cekLengths.get(joseHeader.enc), partyUInfo, partyVInfo);
43
+ const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, parseInt(alg.substr(-5, 3), 10) || cekLength(joseHeader.enc), partyUInfo, partyVInfo);
44
44
  if (alg === 'ECDH-ES')
45
45
  return sharedSecret;
46
46
  if (encryptedKey === undefined)
@@ -2,12 +2,12 @@ import { wrap as aesKw } from '../runtime/aeskw.js';
2
2
  import * as ECDH from '../runtime/ecdhes.js';
3
3
  import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js';
4
4
  import { encrypt as rsaEs } from '../runtime/rsaes.js';
5
- import { wrap as aesGcmKw } from '../runtime/aesgcmkw.js';
6
5
  import { encode as base64url } from '../runtime/base64url.js';
7
- import generateCek, { bitLengths as cekLengths } from '../lib/cek.js';
6
+ import generateCek, { bitLength as cekLength } from '../lib/cek.js';
8
7
  import { JOSENotSupported } from '../util/errors.js';
9
8
  import { exportJWK } from '../key/export.js';
10
9
  import checkKeyType from './check_key_type.js';
10
+ import { wrap as aesGcmKw } from './aesgcmkw.js';
11
11
  async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
12
12
  let encryptedKey;
13
13
  let parameters;
@@ -29,7 +29,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
29
29
  let { epk: ephemeralKey } = providedParameters;
30
30
  ephemeralKey || (ephemeralKey = await ECDH.generateEpk(key));
31
31
  const { x, y, crv, kty } = await exportJWK(ephemeralKey);
32
- const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, parseInt(alg.substr(-5, 3), 10) || cekLengths.get(enc), apu, apv);
32
+ const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, parseInt(alg.substr(-5, 3), 10) || cekLength(enc), apu, apv);
33
33
  parameters = { epk: { x, y, crv, kty } };
34
34
  if (apu)
35
35
  parameters.apu = base64url(apu);
@@ -1,22 +1,27 @@
1
1
  import { JOSENotSupported } from '../util/errors.js';
2
2
  import random from '../runtime/random.js';
3
- const bitLengths = new Map([
4
- ['A128CBC-HS256', 128],
5
- ['A128GCM', 96],
6
- ['A128GCMKW', 96],
7
- ['A192CBC-HS384', 128],
8
- ['A192GCM', 96],
9
- ['A192GCMKW', 96],
10
- ['A256CBC-HS512', 128],
11
- ['A256GCM', 96],
12
- ['A256GCMKW', 96],
13
- ]);
14
- const generateIv = (alg) => {
15
- const bitLength = bitLengths.get(alg);
16
- if (!bitLength) {
17
- throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
3
+ export function bitLength(alg) {
4
+ switch (alg) {
5
+ case 'A128CBC-HS256':
6
+ return 128;
7
+ case 'A128GCM':
8
+ return 96;
9
+ case 'A128GCMKW':
10
+ return 96;
11
+ case 'A192CBC-HS384':
12
+ return 128;
13
+ case 'A192GCM':
14
+ return 96;
15
+ case 'A192GCMKW':
16
+ return 96;
17
+ case 'A256CBC-HS512':
18
+ return 128;
19
+ case 'A256GCM':
20
+ return 96;
21
+ case 'A256GCMKW':
22
+ return 96;
23
+ default:
24
+ throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
18
25
  }
19
- return random(new Uint8Array(bitLength >> 3));
20
- };
21
- export default generateIv;
22
- export { bitLengths };
26
+ }
27
+ export default (alg) => random(new Uint8Array(bitLength(alg) >> 3));
@@ -1,6 +1,7 @@
1
1
  import bogusWebCrypto from './bogus.js';
2
- import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js';
3
- import invalidKeyInput from './invalid_key_input.js';
2
+ import crypto, { isCryptoKey } from './webcrypto.js';
3
+ import { checkEncCryptoKey } from '../lib/crypto_key.js';
4
+ import invalidKeyInput from '../lib/invalid_key_input.js';
4
5
  function checkKeySize(key, alg) {
5
6
  if (key.algorithm.length !== parseInt(alg.substr(1, 3), 10)) {
6
7
  throw new TypeError(`Invalid key size for alg: ${alg}`);
@@ -8,7 +9,7 @@ function checkKeySize(key, alg) {
8
9
  }
9
10
  function getCryptoKey(key, alg, usage) {
10
11
  if (isCryptoKey(key)) {
11
- checkCryptoKey(key, alg, usage);
12
+ checkEncCryptoKey(key, alg, usage);
12
13
  return key;
13
14
  }
14
15
  if (key instanceof Uint8Array) {
@@ -1,6 +1,6 @@
1
1
  import globalThis, { isCloudflareWorkers, isNodeJs } from './global.js';
2
2
  import crypto, { isCryptoKey } from './webcrypto.js';
3
- import invalidKeyInput from './invalid_key_input.js';
3
+ import invalidKeyInput from '../lib/invalid_key_input.js';
4
4
  import { encodeBase64 } from './base64url.js';
5
5
  import formatPEM from '../lib/format_pem.js';
6
6
  import { JOSENotSupported } from '../util/errors.js';
@@ -63,13 +63,13 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
63
63
  case 'PS256':
64
64
  case 'PS384':
65
65
  case 'PS512':
66
- algorithm = { name: 'RSA-PSS', hash: { name: `SHA-${alg.substr(-3)}` } };
66
+ algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.substr(-3)}` };
67
67
  keyUsages = isPublic ? ['verify'] : ['sign'];
68
68
  break;
69
69
  case 'RS256':
70
70
  case 'RS384':
71
71
  case 'RS512':
72
- algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: { name: `SHA-${alg.substr(-3)}` } };
72
+ algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.substr(-3)}` };
73
73
  keyUsages = isPublic ? ['verify'] : ['sign'];
74
74
  break;
75
75
  case 'RSA-OAEP':
@@ -78,7 +78,7 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
78
78
  case 'RSA-OAEP-512':
79
79
  algorithm = {
80
80
  name: 'RSA-OAEP',
81
- hash: { name: `SHA-${parseInt(alg.substr(-3), 10) || 1}` },
81
+ hash: `SHA-${parseInt(alg.substr(-3), 10) || 1}`,
82
82
  };
83
83
  keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'];
84
84
  break;
@@ -1,5 +1,5 @@
1
1
  const bogusWebCrypto = [
2
- { hash: { name: 'SHA-256' }, name: 'HMAC' },
2
+ { hash: 'SHA-256', name: 'HMAC' },
3
3
  true,
4
4
  ['sign'],
5
5
  ];
@@ -0,0 +1,7 @@
1
+ import { JWEInvalid } from '../util/errors.js';
2
+ const checkCekLength = (cek, expected) => {
3
+ if (cek.length << 3 !== expected) {
4
+ throw new JWEInvalid('Invalid Content Encryption Key length');
5
+ }
6
+ };
7
+ export default checkCekLength;
@@ -1,9 +1,11 @@
1
1
  import { concat, uint64be } from '../lib/buffer_utils.js';
2
2
  import checkIvLength from '../lib/check_iv_length.js';
3
+ import checkCekLength from './check_cek_length.js';
3
4
  import timingSafeEqual from './timing_safe_equal.js';
4
5
  import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js';
5
- import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js';
6
- import invalidKeyInput from './invalid_key_input.js';
6
+ import crypto, { isCryptoKey } from './webcrypto.js';
7
+ import { checkEncCryptoKey } from '../lib/crypto_key.js';
8
+ import invalidKeyInput from '../lib/invalid_key_input.js';
7
9
  async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
8
10
  if (!(cek instanceof Uint8Array)) {
9
11
  throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
@@ -11,7 +13,7 @@ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
11
13
  const keySize = parseInt(enc.substr(1, 3), 10);
12
14
  const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']);
13
15
  const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
14
- hash: { name: `SHA-${keySize << 1}` },
16
+ hash: `SHA-${keySize << 1}`,
15
17
  name: 'HMAC',
16
18
  }, false, ['sign']);
17
19
  const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
@@ -42,7 +44,7 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
42
44
  encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']);
43
45
  }
44
46
  else {
45
- checkCryptoKey(cek, enc, 'decrypt');
47
+ checkEncCryptoKey(cek, enc, 'decrypt');
46
48
  encKey = cek;
47
49
  }
48
50
  try {
@@ -66,10 +68,14 @@ const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
66
68
  case 'A128CBC-HS256':
67
69
  case 'A192CBC-HS384':
68
70
  case 'A256CBC-HS512':
71
+ if (cek instanceof Uint8Array)
72
+ checkCekLength(cek, parseInt(enc.substr(-3), 10));
69
73
  return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
70
74
  case 'A128GCM':
71
75
  case 'A192GCM':
72
76
  case 'A256GCM':
77
+ if (cek instanceof Uint8Array)
78
+ checkCekLength(cek, parseInt(enc.substr(1, 3), 10));
73
79
  return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
74
80
  default:
75
81
  throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
@@ -1,16 +1,17 @@
1
1
  import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js';
2
- import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js';
2
+ import crypto, { isCryptoKey } from './webcrypto.js';
3
+ import { checkEncCryptoKey } from '../lib/crypto_key.js';
3
4
  import digest from './digest.js';
4
- import invalidKeyInput from './invalid_key_input.js';
5
+ import invalidKeyInput from '../lib/invalid_key_input.js';
5
6
  export const deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
6
7
  if (!isCryptoKey(publicKey)) {
7
8
  throw new TypeError(invalidKeyInput(publicKey, 'CryptoKey'));
8
9
  }
9
- checkCryptoKey(publicKey, 'ECDH-ES');
10
+ checkEncCryptoKey(publicKey, 'ECDH-ES');
10
11
  if (!isCryptoKey(privateKey)) {
11
12
  throw new TypeError(invalidKeyInput(privateKey, 'CryptoKey'));
12
13
  }
13
- checkCryptoKey(privateKey, 'ECDH-ES', 'deriveBits', 'deriveKey');
14
+ checkEncCryptoKey(privateKey, 'ECDH-ES', 'deriveBits', 'deriveKey');
14
15
  const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
15
16
  if (!privateKey.usages.includes('deriveBits')) {
16
17
  throw new TypeError('ECDH-ES private key "usages" must include "deriveBits"');
@@ -1,7 +1,9 @@
1
1
  import { concat, uint64be } from '../lib/buffer_utils.js';
2
2
  import checkIvLength from '../lib/check_iv_length.js';
3
- import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js';
4
- import invalidKeyInput from './invalid_key_input.js';
3
+ import checkCekLength from './check_cek_length.js';
4
+ import crypto, { isCryptoKey } from './webcrypto.js';
5
+ import { checkEncCryptoKey } from '../lib/crypto_key.js';
6
+ import invalidKeyInput from '../lib/invalid_key_input.js';
5
7
  import { JOSENotSupported } from '../util/errors.js';
6
8
  async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
7
9
  if (!(cek instanceof Uint8Array)) {
@@ -10,7 +12,7 @@ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
10
12
  const keySize = parseInt(enc.substr(1, 3), 10);
11
13
  const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['encrypt']);
12
14
  const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
13
- hash: { name: `SHA-${keySize << 1}` },
15
+ hash: `SHA-${keySize << 1}`,
14
16
  name: 'HMAC',
15
17
  }, false, ['sign']);
16
18
  const ciphertext = new Uint8Array(await crypto.subtle.encrypt({
@@ -27,7 +29,7 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
27
29
  encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']);
28
30
  }
29
31
  else {
30
- checkCryptoKey(cek, enc, 'encrypt');
32
+ checkEncCryptoKey(cek, enc, 'encrypt');
31
33
  encKey = cek;
32
34
  }
33
35
  const encrypted = new Uint8Array(await crypto.subtle.encrypt({
@@ -49,10 +51,14 @@ const encrypt = async (enc, plaintext, cek, iv, aad) => {
49
51
  case 'A128CBC-HS256':
50
52
  case 'A192CBC-HS384':
51
53
  case 'A256CBC-HS512':
54
+ if (cek instanceof Uint8Array)
55
+ checkCekLength(cek, parseInt(enc.substr(-3), 10));
52
56
  return cbcEncrypt(enc, plaintext, cek, iv, aad);
53
57
  case 'A128GCM':
54
58
  case 'A192GCM':
55
59
  case 'A256GCM':
60
+ if (cek instanceof Uint8Array)
61
+ checkCekLength(cek, parseInt(enc.substr(1, 3), 10));
56
62
  return gcmEncrypt(enc, plaintext, cek, iv, aad);
57
63
  default:
58
64
  throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
@@ -12,7 +12,7 @@ export async function generateSecret(alg, options) {
12
12
  case 'HS384':
13
13
  case 'HS512':
14
14
  length = parseInt(alg.substr(-3), 10);
15
- algorithm = { name: 'HMAC', hash: { name: `SHA-${length}` }, length };
15
+ algorithm = { name: 'HMAC', hash: `SHA-${length}`, length };
16
16
  keyUsages = ['sign', 'verify'];
17
17
  break;
18
18
  case 'A128CBC-HS256':
@@ -60,7 +60,7 @@ export async function generateKeyPair(alg, options) {
60
60
  case 'PS512':
61
61
  algorithm = {
62
62
  name: 'RSA-PSS',
63
- hash: { name: `SHA-${alg.substr(-3)}` },
63
+ hash: `SHA-${alg.substr(-3)}`,
64
64
  publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
65
65
  modulusLength: getModulusLengthOption(options),
66
66
  };
@@ -71,7 +71,7 @@ export async function generateKeyPair(alg, options) {
71
71
  case 'RS512':
72
72
  algorithm = {
73
73
  name: 'RSASSA-PKCS1-v1_5',
74
- hash: { name: `SHA-${alg.substr(-3)}` },
74
+ hash: `SHA-${alg.substr(-3)}`,
75
75
  publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
76
76
  modulusLength: getModulusLengthOption(options),
77
77
  };
@@ -83,7 +83,7 @@ export async function generateKeyPair(alg, options) {
83
83
  case 'RSA-OAEP-512':
84
84
  algorithm = {
85
85
  name: 'RSA-OAEP',
86
- hash: { name: `SHA-${parseInt(alg.substr(-3), 10) || 1}` },
86
+ hash: `SHA-${parseInt(alg.substr(-3), 10) || 1}`,
87
87
  publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
88
88
  modulusLength: getModulusLengthOption(options),
89
89
  };
@@ -1,15 +1,16 @@
1
- import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js';
2
- import invalidKeyInput from './invalid_key_input.js';
1
+ import crypto, { isCryptoKey } from './webcrypto.js';
2
+ import { checkSigCryptoKey } from '../lib/crypto_key.js';
3
+ import invalidKeyInput from '../lib/invalid_key_input.js';
3
4
  export default function getCryptoKey(alg, key, usage) {
4
5
  if (isCryptoKey(key)) {
5
- checkCryptoKey(key, alg, usage);
6
+ checkSigCryptoKey(key, alg, usage);
6
7
  return key;
7
8
  }
8
9
  if (key instanceof Uint8Array) {
9
10
  if (!alg.startsWith('HS')) {
10
11
  throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
11
12
  }
12
- return crypto.subtle.importKey('raw', key, { hash: { name: `SHA-${alg.substr(-3)}` }, name: 'HMAC' }, false, [usage]);
13
+ return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.substr(-3)}`, name: 'HMAC' }, false, [usage]);
13
14
  }
14
15
  throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
15
16
  }
@@ -11,7 +11,7 @@ function subtleMapping(jwk) {
11
11
  case 'HS256':
12
12
  case 'HS384':
13
13
  case 'HS512':
14
- algorithm = { name: 'HMAC', hash: { name: `SHA-${jwk.alg.substr(-3)}` } };
14
+ algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.substr(-3)}` };
15
15
  keyUsages = ['sign', 'verify'];
16
16
  break;
17
17
  case 'A128CBC-HS256':
@@ -49,13 +49,13 @@ function subtleMapping(jwk) {
49
49
  case 'PS256':
50
50
  case 'PS384':
51
51
  case 'PS512':
52
- algorithm = { name: 'RSA-PSS', hash: { name: `SHA-${jwk.alg.substr(-3)}` } };
52
+ algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.substr(-3)}` };
53
53
  keyUsages = jwk.d ? ['sign'] : ['verify'];
54
54
  break;
55
55
  case 'RS256':
56
56
  case 'RS384':
57
57
  case 'RS512':
58
- algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: { name: `SHA-${jwk.alg.substr(-3)}` } };
58
+ algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.substr(-3)}` };
59
59
  keyUsages = jwk.d ? ['sign'] : ['verify'];
60
60
  break;
61
61
  case 'RSA-OAEP':
@@ -64,7 +64,7 @@ function subtleMapping(jwk) {
64
64
  case 'RSA-OAEP-512':
65
65
  algorithm = {
66
66
  name: 'RSA-OAEP',
67
- hash: { name: `SHA-${parseInt(jwk.alg.substr(-3), 10) || 1}` },
67
+ hash: `SHA-${parseInt(jwk.alg.substr(-3), 10) || 1}`,
68
68
  };
69
69
  keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];
70
70
  break;
@@ -1,5 +1,5 @@
1
1
  import crypto, { isCryptoKey } from './webcrypto.js';
2
- import invalidKeyInput from './invalid_key_input.js';
2
+ import invalidKeyInput from '../lib/invalid_key_input.js';
3
3
  import { encode as base64url } from './base64url.js';
4
4
  const keyToJWK = async (key) => {
5
5
  if (key instanceof Uint8Array) {