jose 4.2.0 → 4.3.3

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 (64) hide show
  1. package/README.md +15 -0
  2. package/dist/browser/jwe/general/encrypt.js +33 -23
  3. package/dist/browser/jwks/remote.js +16 -12
  4. package/dist/browser/jws/general/sign.js +25 -29
  5. package/dist/browser/lib/cek.js +5 -6
  6. package/dist/browser/lib/decrypt_key_management.js +1 -1
  7. package/dist/browser/lib/encrypt_key_management.js +1 -1
  8. package/dist/browser/lib/iv.js +4 -11
  9. package/dist/browser/runtime/aeskw.js +2 -1
  10. package/dist/browser/runtime/asn1.js +2 -1
  11. package/dist/browser/runtime/decrypt.js +2 -1
  12. package/dist/browser/runtime/ecdhes.js +5 -4
  13. package/dist/browser/runtime/encrypt.js +2 -1
  14. package/dist/browser/runtime/get_sign_verify_key.js +3 -2
  15. package/dist/browser/runtime/key_to_jwk.js +2 -1
  16. package/dist/browser/runtime/pbes2kw.js +2 -1
  17. package/dist/browser/runtime/rsaes.js +3 -2
  18. package/dist/node/cjs/jwe/general/encrypt.js +33 -23
  19. package/dist/node/cjs/jwks/remote.js +16 -12
  20. package/dist/node/cjs/jws/general/sign.js +25 -29
  21. package/dist/node/cjs/lib/cek.js +5 -6
  22. package/dist/node/cjs/lib/decrypt_key_management.js +1 -1
  23. package/dist/node/cjs/lib/encrypt_key_management.js +1 -1
  24. package/dist/node/cjs/lib/iv.js +4 -11
  25. package/dist/node/cjs/runtime/aeskw.js +4 -3
  26. package/dist/node/cjs/runtime/asn1.js +2 -1
  27. package/dist/node/cjs/runtime/decrypt.js +5 -4
  28. package/dist/node/cjs/runtime/ecdhes.js +5 -4
  29. package/dist/node/cjs/runtime/encrypt.js +5 -4
  30. package/dist/node/cjs/runtime/get_named_curve.js +2 -1
  31. package/dist/node/cjs/runtime/get_sign_verify_key.js +3 -2
  32. package/dist/node/cjs/runtime/key_to_jwk.js +2 -1
  33. package/dist/node/cjs/runtime/pbes2kw.js +2 -1
  34. package/dist/node/cjs/runtime/rsaes.js +4 -3
  35. package/dist/node/esm/jwe/general/encrypt.js +33 -23
  36. package/dist/node/esm/jwks/remote.js +16 -12
  37. package/dist/node/esm/jws/general/sign.js +25 -29
  38. package/dist/node/esm/lib/cek.js +5 -6
  39. package/dist/node/esm/lib/decrypt_key_management.js +1 -1
  40. package/dist/node/esm/lib/encrypt_key_management.js +1 -1
  41. package/dist/node/esm/lib/iv.js +4 -11
  42. package/dist/node/esm/runtime/aeskw.js +4 -3
  43. package/dist/node/esm/runtime/asn1.js +2 -1
  44. package/dist/node/esm/runtime/decrypt.js +5 -4
  45. package/dist/node/esm/runtime/ecdhes.js +5 -4
  46. package/dist/node/esm/runtime/encrypt.js +5 -4
  47. package/dist/node/esm/runtime/get_named_curve.js +2 -1
  48. package/dist/node/esm/runtime/get_sign_verify_key.js +3 -2
  49. package/dist/node/esm/runtime/key_to_jwk.js +2 -1
  50. package/dist/node/esm/runtime/pbes2kw.js +2 -1
  51. package/dist/node/esm/runtime/rsaes.js +4 -3
  52. package/dist/types/index.d.ts +1 -1
  53. package/dist/types/jwe/compact/decrypt.d.ts +2 -2
  54. package/dist/types/jwe/compact/encrypt.d.ts +2 -2
  55. package/dist/types/jwe/general/encrypt.d.ts +3 -0
  56. package/dist/types/jws/compact/sign.d.ts +2 -2
  57. package/dist/types/jws/compact/verify.d.ts +2 -2
  58. package/dist/types/jws/general/sign.d.ts +3 -0
  59. package/dist/types/jwt/decrypt.d.ts +2 -2
  60. package/dist/types/jwt/encrypt.d.ts +2 -2
  61. package/dist/types/jwt/sign.d.ts +2 -2
  62. package/dist/types/jwt/verify.d.ts +2 -2
  63. package/dist/types/types.d.ts +19 -17
  64. package/package.json +1 -1
package/README.md CHANGED
@@ -25,6 +25,21 @@ If you or your business use `jose`, please consider becoming a [sponsor][support
25
25
 
26
26
  ## Documentation
27
27
 
28
+ **`example`** ESM import
29
+ ```js
30
+ import * as jose from 'jose'
31
+ ```
32
+
33
+ **`example`** CJS require
34
+ ```js
35
+ const jose = require('jose')
36
+ ```
37
+
38
+ **`example`** Deno import
39
+ ```js
40
+ import * as jose from 'https://deno.land/x/jose/index.ts'
41
+ ```
42
+
28
43
  - JSON Web Tokens (JWT)
29
44
  - [Signing](docs/classes/jwt_sign.SignJWT.md#readme)
30
45
  - [Verification & Claims Set Validation](docs/functions/jwt_verify.jwtVerify.md#readme)
@@ -5,20 +5,27 @@ import isDisjoint from '../../lib/is_disjoint.js';
5
5
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
6
6
  import { encode as base64url } from '../../runtime/base64url.js';
7
7
  import validateCrit from '../../lib/validate_crit.js';
8
- const recipientRef = new WeakMap();
9
8
  class IndividualRecipient {
9
+ constructor(enc, key, options) {
10
+ this.parent = enc;
11
+ this.key = key;
12
+ this.options = options;
13
+ }
10
14
  setUnprotectedHeader(unprotectedHeader) {
11
- if (this._unprotectedHeader) {
15
+ if (this.unprotectedHeader) {
12
16
  throw new TypeError('setUnprotectedHeader can only be called once');
13
17
  }
14
- this._unprotectedHeader = unprotectedHeader;
18
+ this.unprotectedHeader = unprotectedHeader;
15
19
  return this;
16
20
  }
17
- set _unprotectedHeader(value) {
18
- recipientRef.get(this).unprotectedHeader = value;
21
+ addRecipient(...args) {
22
+ return this.parent.addRecipient(...args);
23
+ }
24
+ encrypt(...args) {
25
+ return this.parent.encrypt(...args);
19
26
  }
20
- get _unprotectedHeader() {
21
- return recipientRef.get(this).unprotectedHeader;
27
+ done() {
28
+ return this.parent;
22
29
  }
23
30
  }
24
31
  export class GeneralEncrypt {
@@ -27,8 +34,7 @@ export class GeneralEncrypt {
27
34
  this._plaintext = plaintext;
28
35
  }
29
36
  addRecipient(key, options) {
30
- const recipient = new IndividualRecipient();
31
- recipientRef.set(recipient, { key, options: { crit: options === null || options === void 0 ? void 0 : options.crit } });
37
+ const recipient = new IndividualRecipient(this, key, { crit: options === null || options === void 0 ? void 0 : options.crit });
32
38
  this._recipients.push(recipient);
33
39
  return recipient;
34
40
  }
@@ -51,19 +57,19 @@ export class GeneralEncrypt {
51
57
  return this;
52
58
  }
53
59
  async encrypt(options) {
54
- var _a, _b;
60
+ var _a, _b, _c;
55
61
  if (!this._recipients.length) {
56
62
  throw new JWEInvalid('at least one recipient must be added');
57
63
  }
58
64
  options = { deflateRaw: options === null || options === void 0 ? void 0 : options.deflateRaw };
59
65
  if (this._recipients.length === 1) {
60
- const { unprotectedHeader, options: recipientOpts, key, } = recipientRef.get(this._recipients[0]);
66
+ const [recipient] = this._recipients;
61
67
  const flattened = await new FlattenedEncrypt(this._plaintext)
62
68
  .setAdditionalAuthenticatedData(this._aad)
63
69
  .setProtectedHeader(this._protectedHeader)
64
70
  .setSharedUnprotectedHeader(this._unprotectedHeader)
65
- .setUnprotectedHeader(unprotectedHeader)
66
- .encrypt(key, { ...recipientOpts, ...options });
71
+ .setUnprotectedHeader(recipient.unprotectedHeader)
72
+ .encrypt(recipient.key, { ...recipient.options, ...options });
67
73
  let jwe = {
68
74
  ciphertext: flattened.ciphertext,
69
75
  iv: flattened.iv,
@@ -85,14 +91,13 @@ export class GeneralEncrypt {
85
91
  let enc;
86
92
  for (let i = 0; i < this._recipients.length; i++) {
87
93
  const recipient = this._recipients[i];
88
- const { unprotectedHeader, options: recipientOpts } = recipientRef.get(recipient);
89
- if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, unprotectedHeader)) {
94
+ if (!isDisjoint(this._protectedHeader, this._unprotectedHeader, recipient.unprotectedHeader)) {
90
95
  throw new JWEInvalid('JWE Protected, JWE Shared Unprotected and JWE Per-Recipient Header Parameter names must be disjoint');
91
96
  }
92
97
  const joseHeader = {
93
98
  ...this._protectedHeader,
94
99
  ...this._unprotectedHeader,
95
- ...unprotectedHeader,
100
+ ...recipient.unprotectedHeader,
96
101
  };
97
102
  const { alg } = joseHeader;
98
103
  if (typeof alg !== 'string' || !alg) {
@@ -110,7 +115,7 @@ export class GeneralEncrypt {
110
115
  else if (enc !== joseHeader.enc) {
111
116
  throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter must be the same for all recipients');
112
117
  }
113
- validateCrit(JWEInvalid, new Map(), recipientOpts === null || recipientOpts === void 0 ? void 0 : recipientOpts.crit, this._protectedHeader, joseHeader);
118
+ validateCrit(JWEInvalid, new Map(), recipient.options.crit, this._protectedHeader, joseHeader);
114
119
  if (joseHeader.zip !== undefined) {
115
120
  if (!this._protectedHeader || !this._protectedHeader.zip) {
116
121
  throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
@@ -128,15 +133,18 @@ export class GeneralEncrypt {
128
133
  const recipient = this._recipients[i];
129
134
  const target = {};
130
135
  jwe.recipients.push(target);
131
- const { unprotectedHeader, options: recipientOpts, key } = recipientRef.get(recipient);
132
136
  if (i === 0) {
133
137
  const flattened = await new FlattenedEncrypt(this._plaintext)
134
138
  .setAdditionalAuthenticatedData(this._aad)
135
139
  .setContentEncryptionKey(cek)
136
140
  .setProtectedHeader(this._protectedHeader)
137
141
  .setSharedUnprotectedHeader(this._unprotectedHeader)
138
- .setUnprotectedHeader(unprotectedHeader)
139
- .encrypt(key, { ...recipientOpts, ...options, [unprotected]: true });
142
+ .setUnprotectedHeader(recipient.unprotectedHeader)
143
+ .encrypt(recipient.key, {
144
+ ...recipient.options,
145
+ ...options,
146
+ [unprotected]: true,
147
+ });
140
148
  jwe.ciphertext = flattened.ciphertext;
141
149
  jwe.iv = flattened.iv;
142
150
  jwe.tag = flattened.tag;
@@ -151,10 +159,12 @@ export class GeneralEncrypt {
151
159
  target.header = flattened.header;
152
160
  continue;
153
161
  }
154
- const { encryptedKey, parameters } = await encryptKeyManagement((unprotectedHeader === null || unprotectedHeader === void 0 ? void 0 : unprotectedHeader.alg) || ((_a = this._protectedHeader) === null || _a === void 0 ? void 0 : _a.alg) || ((_b = this._unprotectedHeader) === null || _b === void 0 ? void 0 : _b.alg), enc, key, cek);
162
+ const { encryptedKey, parameters } = await encryptKeyManagement(((_a = recipient.unprotectedHeader) === null || _a === void 0 ? void 0 : _a.alg) ||
163
+ ((_b = this._protectedHeader) === null || _b === void 0 ? void 0 : _b.alg) ||
164
+ ((_c = this._unprotectedHeader) === null || _c === void 0 ? void 0 : _c.alg), enc, recipient.key, cek);
155
165
  target.encrypted_key = base64url(encryptedKey);
156
- if (unprotectedHeader || parameters)
157
- target.header = { ...unprotectedHeader, ...parameters };
166
+ if (recipient.unprotectedHeader || parameters)
167
+ target.header = { ...recipient.unprotectedHeader, ...parameters };
158
168
  }
159
169
  return jwe;
160
170
  }
@@ -37,17 +37,21 @@ class RemoteJWKSet {
37
37
  }
38
38
  return Date.now() < this._cooldownStarted + this._cooldownDuration;
39
39
  }
40
- async getKey(protectedHeader) {
40
+ async getKey(protectedHeader, token) {
41
+ const joseHeader = {
42
+ ...protectedHeader,
43
+ ...token.header,
44
+ };
41
45
  if (!this._jwks) {
42
46
  await this.reload();
43
47
  }
44
48
  const candidates = this._jwks.keys.filter((jwk) => {
45
- let candidate = jwk.kty === getKtyFromAlg(protectedHeader.alg);
46
- if (candidate && typeof protectedHeader.kid === 'string') {
47
- candidate = protectedHeader.kid === jwk.kid;
49
+ let candidate = jwk.kty === getKtyFromAlg(joseHeader.alg);
50
+ if (candidate && typeof joseHeader.kid === 'string') {
51
+ candidate = joseHeader.kid === jwk.kid;
48
52
  }
49
53
  if (candidate && typeof jwk.alg === 'string') {
50
- candidate = protectedHeader.alg === jwk.alg;
54
+ candidate = joseHeader.alg === jwk.alg;
51
55
  }
52
56
  if (candidate && typeof jwk.use === 'string') {
53
57
  candidate = jwk.use === 'sig';
@@ -55,11 +59,11 @@ class RemoteJWKSet {
55
59
  if (candidate && Array.isArray(jwk.key_ops)) {
56
60
  candidate = jwk.key_ops.includes('verify');
57
61
  }
58
- if (candidate && protectedHeader.alg === 'EdDSA') {
62
+ if (candidate && joseHeader.alg === 'EdDSA') {
59
63
  candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';
60
64
  }
61
65
  if (candidate) {
62
- switch (protectedHeader.alg) {
66
+ switch (joseHeader.alg) {
63
67
  case 'ES256':
64
68
  candidate = jwk.crv === 'P-256';
65
69
  break;
@@ -81,7 +85,7 @@ class RemoteJWKSet {
81
85
  if (length === 0) {
82
86
  if (this.coolingDown() === false) {
83
87
  await this.reload();
84
- return this.getKey(protectedHeader);
88
+ return this.getKey(protectedHeader, token);
85
89
  }
86
90
  throw new JWKSNoMatchingKey();
87
91
  }
@@ -89,14 +93,14 @@ class RemoteJWKSet {
89
93
  throw new JWKSMultipleMatchingKeys();
90
94
  }
91
95
  const cached = this._cached.get(jwk) || this._cached.set(jwk, {}).get(jwk);
92
- if (cached[protectedHeader.alg] === undefined) {
93
- const keyObject = await importJWK({ ...jwk, ext: true }, protectedHeader.alg);
96
+ if (cached[joseHeader.alg] === undefined) {
97
+ const keyObject = await importJWK({ ...jwk, ext: true }, joseHeader.alg);
94
98
  if (keyObject instanceof Uint8Array || keyObject.type !== 'public') {
95
99
  throw new JWKSInvalid('JSON Web Key Set members must be public keys');
96
100
  }
97
- cached[protectedHeader.alg] = keyObject;
101
+ cached[joseHeader.alg] = keyObject;
98
102
  }
99
- return cached[protectedHeader.alg];
103
+ return cached[joseHeader.alg];
100
104
  }
101
105
  async reload() {
102
106
  if (!this._pendingFetch) {
@@ -1,32 +1,33 @@
1
1
  import { FlattenedSign } from '../flattened/sign.js';
2
2
  import { JWSInvalid } from '../../util/errors.js';
3
- const signatureRef = new WeakMap();
4
3
  class IndividualSignature {
4
+ constructor(sig, key, options) {
5
+ this.parent = sig;
6
+ this.key = key;
7
+ this.options = options;
8
+ }
5
9
  setProtectedHeader(protectedHeader) {
6
- if (this._protectedHeader) {
10
+ if (this.protectedHeader) {
7
11
  throw new TypeError('setProtectedHeader can only be called once');
8
12
  }
9
- this._protectedHeader = protectedHeader;
13
+ this.protectedHeader = protectedHeader;
10
14
  return this;
11
15
  }
12
16
  setUnprotectedHeader(unprotectedHeader) {
13
- if (this._unprotectedHeader) {
17
+ if (this.unprotectedHeader) {
14
18
  throw new TypeError('setUnprotectedHeader can only be called once');
15
19
  }
16
- this._unprotectedHeader = unprotectedHeader;
20
+ this.unprotectedHeader = unprotectedHeader;
17
21
  return this;
18
22
  }
19
- set _protectedHeader(value) {
20
- signatureRef.get(this).protectedHeader = value;
21
- }
22
- get _protectedHeader() {
23
- return signatureRef.get(this).protectedHeader;
23
+ addSignature(...args) {
24
+ return this.parent.addSignature(...args);
24
25
  }
25
- set _unprotectedHeader(value) {
26
- signatureRef.get(this).unprotectedHeader = value;
26
+ sign(...args) {
27
+ return this.parent.sign(...args);
27
28
  }
28
- get _unprotectedHeader() {
29
- return signatureRef.get(this).unprotectedHeader;
29
+ done() {
30
+ return this.parent;
30
31
  }
31
32
  }
32
33
  export class GeneralSign {
@@ -35,8 +36,7 @@ export class GeneralSign {
35
36
  this._payload = payload;
36
37
  }
37
38
  addSignature(key, options) {
38
- const signature = new IndividualSignature();
39
- signatureRef.set(signature, { key, options });
39
+ const signature = new IndividualSignature(this, key, options);
40
40
  this._signatures.push(signature);
41
41
  return signature;
42
42
  }
@@ -48,23 +48,19 @@ export class GeneralSign {
48
48
  signatures: [],
49
49
  payload: '',
50
50
  };
51
- let payloads = new Set();
52
- await Promise.all(this._signatures.map(async (sig) => {
53
- const { protectedHeader, unprotectedHeader, options, key } = signatureRef.get(sig);
51
+ for (let i = 0; i < this._signatures.length; i++) {
52
+ const signature = this._signatures[i];
54
53
  const flattened = new FlattenedSign(this._payload);
55
- if (protectedHeader) {
56
- flattened.setProtectedHeader(protectedHeader);
54
+ flattened.setProtectedHeader(signature.protectedHeader);
55
+ flattened.setUnprotectedHeader(signature.unprotectedHeader);
56
+ const { payload, ...rest } = await flattened.sign(signature.key, signature.options);
57
+ if (i === 0) {
58
+ jws.payload = payload;
57
59
  }
58
- if (unprotectedHeader) {
59
- flattened.setUnprotectedHeader(unprotectedHeader);
60
+ else if (jws.payload !== payload) {
61
+ throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)');
60
62
  }
61
- const { payload, ...rest } = await flattened.sign(key, options);
62
- payloads.add(payload);
63
- jws.payload = payload;
64
63
  jws.signatures.push(rest);
65
- }));
66
- if (payloads.size !== 1) {
67
- throw new JWSInvalid('inconsistent use of JWS Unencoded Payload Option (RFC7797)');
68
64
  }
69
65
  return jws;
70
66
  }
@@ -2,18 +2,17 @@ import { JOSENotSupported } from '../util/errors.js';
2
2
  import random from '../runtime/random.js';
3
3
  export function bitLength(alg) {
4
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
5
  case 'A128GCM':
12
6
  return 128;
13
7
  case 'A192GCM':
14
8
  return 192;
15
9
  case 'A256GCM':
10
+ case 'A128CBC-HS256':
16
11
  return 256;
12
+ case 'A192CBC-HS384':
13
+ return 384;
14
+ case 'A256CBC-HS512':
15
+ return 512;
17
16
  default:
18
17
  throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
19
18
  }
@@ -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) || cekLength(joseHeader.enc), partyUInfo, partyVInfo);
43
+ const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.substr(-5, 3), 10), partyUInfo, partyVInfo);
44
44
  if (alg === 'ECDH-ES')
45
45
  return sharedSecret;
46
46
  if (encryptedKey === undefined)
@@ -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) || cekLength(enc), apu, apv);
32
+ const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.substr(-5, 3), 10), apu, apv);
33
33
  parameters = { epk: { x, y, crv, kty } };
34
34
  if (apu)
35
35
  parameters.apu = base64url(apu);
@@ -2,24 +2,17 @@ import { JOSENotSupported } from '../util/errors.js';
2
2
  import random from '../runtime/random.js';
3
3
  export function bitLength(alg) {
4
4
  switch (alg) {
5
- case 'A128CBC-HS256':
6
- return 128;
7
5
  case 'A128GCM':
8
- return 96;
9
6
  case 'A128GCMKW':
10
- return 96;
11
- case 'A192CBC-HS384':
12
- return 128;
13
7
  case 'A192GCM':
14
- return 96;
15
8
  case 'A192GCMKW':
16
- return 96;
17
- case 'A256CBC-HS512':
18
- return 128;
19
9
  case 'A256GCM':
20
- return 96;
21
10
  case 'A256GCMKW':
22
11
  return 96;
12
+ case 'A128CBC-HS256':
13
+ case 'A192CBC-HS384':
14
+ case 'A256CBC-HS512':
15
+ return 128;
23
16
  default:
24
17
  throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
25
18
  }
@@ -2,6 +2,7 @@ import bogusWebCrypto from './bogus.js';
2
2
  import crypto, { isCryptoKey } from './webcrypto.js';
3
3
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
4
4
  import invalidKeyInput from '../lib/invalid_key_input.js';
5
+ import { types } from './is_key_like.js';
5
6
  function checkKeySize(key, alg) {
6
7
  if (key.algorithm.length !== parseInt(alg.substr(1, 3), 10)) {
7
8
  throw new TypeError(`Invalid key size for alg: ${alg}`);
@@ -15,7 +16,7 @@ function getCryptoKey(key, alg, usage) {
15
16
  if (key instanceof Uint8Array) {
16
17
  return crypto.subtle.importKey('raw', key, 'AES-KW', true, [usage]);
17
18
  }
18
- throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
19
+ throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
19
20
  }
20
21
  export const wrap = async (alg, key, cek) => {
21
22
  const cryptoKey = await getCryptoKey(key, alg, 'wrapKey');
@@ -4,9 +4,10 @@ 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';
7
+ import { types } from './is_key_like.js';
7
8
  const genericExport = async (keyType, keyFormat, key) => {
8
9
  if (!isCryptoKey(key)) {
9
- throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
10
+ throw new TypeError(invalidKeyInput(key, ...types));
10
11
  }
11
12
  if (!key.extractable) {
12
13
  throw new TypeError('CryptoKey is not extractable');
@@ -6,6 +6,7 @@ import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js';
6
6
  import crypto, { isCryptoKey } from './webcrypto.js';
7
7
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
8
8
  import invalidKeyInput from '../lib/invalid_key_input.js';
9
+ import { types } from './is_key_like.js';
9
10
  async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
10
11
  if (!(cek instanceof Uint8Array)) {
11
12
  throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
@@ -61,7 +62,7 @@ async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
61
62
  }
62
63
  const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
63
64
  if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
64
- throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'Uint8Array'));
65
+ throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array'));
65
66
  }
66
67
  checkIvLength(enc, iv);
67
68
  switch (enc) {
@@ -3,13 +3,14 @@ import crypto, { isCryptoKey } from './webcrypto.js';
3
3
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
4
4
  import digest from './digest.js';
5
5
  import invalidKeyInput from '../lib/invalid_key_input.js';
6
+ import { types } from './is_key_like.js';
6
7
  export const deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
7
8
  if (!isCryptoKey(publicKey)) {
8
- throw new TypeError(invalidKeyInput(publicKey, 'CryptoKey'));
9
+ throw new TypeError(invalidKeyInput(publicKey, ...types));
9
10
  }
10
11
  checkEncCryptoKey(publicKey, 'ECDH-ES');
11
12
  if (!isCryptoKey(privateKey)) {
12
- throw new TypeError(invalidKeyInput(privateKey, 'CryptoKey'));
13
+ throw new TypeError(invalidKeyInput(privateKey, ...types));
13
14
  }
14
15
  checkEncCryptoKey(privateKey, 'ECDH-ES', 'deriveBits', 'deriveKey');
15
16
  const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
@@ -25,13 +26,13 @@ export const deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu
25
26
  };
26
27
  export const generateEpk = async (key) => {
27
28
  if (!isCryptoKey(key)) {
28
- throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
29
+ throw new TypeError(invalidKeyInput(key, ...types));
29
30
  }
30
31
  return (await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: key.algorithm.namedCurve }, true, ['deriveBits'])).privateKey;
31
32
  };
32
33
  export const ecdhAllowed = (key) => {
33
34
  if (!isCryptoKey(key)) {
34
- throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
35
+ throw new TypeError(invalidKeyInput(key, ...types));
35
36
  }
36
37
  return ['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve);
37
38
  };
@@ -5,6 +5,7 @@ import crypto, { isCryptoKey } from './webcrypto.js';
5
5
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
6
6
  import invalidKeyInput from '../lib/invalid_key_input.js';
7
7
  import { JOSENotSupported } from '../util/errors.js';
8
+ import { types } from './is_key_like.js';
8
9
  async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
9
10
  if (!(cek instanceof Uint8Array)) {
10
11
  throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
@@ -44,7 +45,7 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
44
45
  }
45
46
  const encrypt = async (enc, plaintext, cek, iv, aad) => {
46
47
  if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
47
- throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'Uint8Array'));
48
+ throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array'));
48
49
  }
49
50
  checkIvLength(enc, iv);
50
51
  switch (enc) {
@@ -1,6 +1,7 @@
1
1
  import crypto, { isCryptoKey } from './webcrypto.js';
2
2
  import { checkSigCryptoKey } from '../lib/crypto_key.js';
3
3
  import invalidKeyInput from '../lib/invalid_key_input.js';
4
+ import { types } from './is_key_like.js';
4
5
  export default function getCryptoKey(alg, key, usage) {
5
6
  if (isCryptoKey(key)) {
6
7
  checkSigCryptoKey(key, alg, usage);
@@ -8,9 +9,9 @@ export default function getCryptoKey(alg, key, usage) {
8
9
  }
9
10
  if (key instanceof Uint8Array) {
10
11
  if (!alg.startsWith('HS')) {
11
- throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
12
+ throw new TypeError(invalidKeyInput(key, ...types));
12
13
  }
13
14
  return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.substr(-3)}`, name: 'HMAC' }, false, [usage]);
14
15
  }
15
- throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
16
+ throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
16
17
  }
@@ -1,6 +1,7 @@
1
1
  import crypto, { isCryptoKey } from './webcrypto.js';
2
2
  import invalidKeyInput from '../lib/invalid_key_input.js';
3
3
  import { encode as base64url } from './base64url.js';
4
+ import { types } from './is_key_like.js';
4
5
  const keyToJWK = async (key) => {
5
6
  if (key instanceof Uint8Array) {
6
7
  return {
@@ -9,7 +10,7 @@ const keyToJWK = async (key) => {
9
10
  };
10
11
  }
11
12
  if (!isCryptoKey(key)) {
12
- throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
13
+ throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
13
14
  }
14
15
  if (!key.extractable) {
15
16
  throw new TypeError('non-extractable CryptoKey cannot be exported as a JWK');
@@ -6,6 +6,7 @@ import checkP2s from '../lib/check_p2s.js';
6
6
  import crypto, { isCryptoKey } from './webcrypto.js';
7
7
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
8
8
  import invalidKeyInput from '../lib/invalid_key_input.js';
9
+ import { types } from './is_key_like.js';
9
10
  function getCryptoKey(key, alg) {
10
11
  if (key instanceof Uint8Array) {
11
12
  return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']);
@@ -14,7 +15,7 @@ function getCryptoKey(key, alg) {
14
15
  checkEncCryptoKey(key, alg, 'deriveBits', 'deriveKey');
15
16
  return key;
16
17
  }
17
- throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'Uint8Array'));
18
+ throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
18
19
  }
19
20
  async function deriveKey(p2s, alg, p2c, key) {
20
21
  checkP2s(p2s);
@@ -4,9 +4,10 @@ import crypto, { isCryptoKey } from './webcrypto.js';
4
4
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
5
5
  import checkKeyLength from './check_key_length.js';
6
6
  import invalidKeyInput from '../lib/invalid_key_input.js';
7
+ import { types } from './is_key_like.js';
7
8
  export const encrypt = async (alg, key, cek) => {
8
9
  if (!isCryptoKey(key)) {
9
- throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
10
+ throw new TypeError(invalidKeyInput(key, ...types));
10
11
  }
11
12
  checkEncCryptoKey(key, alg, 'encrypt', 'wrapKey');
12
13
  checkKeyLength(alg, key);
@@ -21,7 +22,7 @@ export const encrypt = async (alg, key, cek) => {
21
22
  };
22
23
  export const decrypt = async (alg, key, encryptedKey) => {
23
24
  if (!isCryptoKey(key)) {
24
- throw new TypeError(invalidKeyInput(key, 'CryptoKey'));
25
+ throw new TypeError(invalidKeyInput(key, ...types));
25
26
  }
26
27
  checkEncCryptoKey(key, alg, 'decrypt', 'unwrapKey');
27
28
  checkKeyLength(alg, key);