jose 5.2.2 → 5.2.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.
@@ -1,6 +1,5 @@
1
1
  import { encode as base64url } from '../../runtime/base64url.js';
2
2
  import encrypt from '../../runtime/encrypt.js';
3
- import generateIv from '../../lib/iv.js';
4
3
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
5
4
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
6
5
  import isDisjoint from '../../lib/is_disjoint.js';
@@ -84,15 +83,8 @@ export class FlattenedEncrypt {
84
83
  throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
85
84
  }
86
85
  let encryptedKey;
87
- if (alg === 'dir') {
88
- if (this._cek) {
89
- throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption');
90
- }
91
- }
92
- else if (alg === 'ECDH-ES') {
93
- if (this._cek) {
94
- throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement');
95
- }
86
+ if (this._cek && (alg === 'dir' || alg === 'ECDH-ES')) {
87
+ throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
96
88
  }
97
89
  let cek;
98
90
  {
@@ -117,7 +109,6 @@ export class FlattenedEncrypt {
117
109
  }
118
110
  }
119
111
  }
120
- this._iv || (this._iv = generateIv(enc));
121
112
  let additionalData;
122
113
  let protectedHeader;
123
114
  let aadMember;
@@ -134,12 +125,16 @@ export class FlattenedEncrypt {
134
125
  else {
135
126
  additionalData = protectedHeader;
136
127
  }
137
- const { ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData);
128
+ const { ciphertext, tag, iv } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData);
138
129
  const jwe = {
139
130
  ciphertext: base64url(ciphertext),
140
- iv: base64url(this._iv),
141
- tag: base64url(tag),
142
131
  };
132
+ if (iv) {
133
+ jwe.iv = base64url(iv);
134
+ }
135
+ if (tag) {
136
+ jwe.tag = base64url(tag);
137
+ }
143
138
  if (encryptedKey) {
144
139
  jwe.encrypted_key = base64url(encryptedKey);
145
140
  }
@@ -9,7 +9,7 @@ function isCloudflareWorkers() {
9
9
  let USER_AGENT;
10
10
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
11
11
  const NAME = 'jose';
12
- const VERSION = 'v5.2.2';
12
+ const VERSION = 'v5.2.3';
13
13
  USER_AGENT = `${NAME}/${VERSION}`;
14
14
  }
15
15
  class RemoteJWKSet extends LocalJWKSet {
@@ -1,12 +1,14 @@
1
1
  import encrypt from '../runtime/encrypt.js';
2
2
  import decrypt from '../runtime/decrypt.js';
3
- import generateIv from './iv.js';
4
3
  import { encode as base64url } from '../runtime/base64url.js';
5
4
  export async function wrap(alg, key, cek, iv) {
6
5
  const jweAlgorithm = alg.slice(0, 7);
7
- iv || (iv = generateIv(jweAlgorithm));
8
- const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
9
- return { encryptedKey, iv: base64url(iv), tag: base64url(tag) };
6
+ const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
7
+ return {
8
+ encryptedKey: wrapped.ciphertext,
9
+ iv: base64url(wrapped.iv),
10
+ tag: base64url(wrapped.tag),
11
+ };
10
12
  }
11
13
  export async function unwrap(alg, key, encryptedKey, iv, tag) {
12
14
  const jweAlgorithm = alg.slice(0, 7);
@@ -1,6 +1,6 @@
1
1
  import { JOSENotSupported } from '../util/errors.js';
2
2
  function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
3
- if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) {
3
+ if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
4
4
  throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
5
5
  }
6
6
  if (!protectedHeader || protectedHeader.crit === undefined) {
@@ -4,6 +4,7 @@ import checkCekLength from './check_cek_length.js';
4
4
  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
+ import generateIv from '../lib/iv.js';
7
8
  import { JOSENotSupported } from '../util/errors.js';
8
9
  import { types } from './is_key_like.js';
9
10
  async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
@@ -22,7 +23,7 @@ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
22
23
  }, encKey, plaintext));
23
24
  const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
24
25
  const tag = new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3));
25
- return { ciphertext, tag };
26
+ return { ciphertext, tag, iv };
26
27
  }
27
28
  async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
28
29
  let encKey;
@@ -41,25 +42,32 @@ async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
41
42
  }, encKey, plaintext));
42
43
  const tag = encrypted.slice(-16);
43
44
  const ciphertext = encrypted.slice(0, -16);
44
- return { ciphertext, tag };
45
+ return { ciphertext, tag, iv };
45
46
  }
46
47
  const encrypt = async (enc, plaintext, cek, iv, aad) => {
47
48
  if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
48
49
  throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array'));
49
50
  }
50
- checkIvLength(enc, iv);
51
+ if (iv) {
52
+ checkIvLength(enc, iv);
53
+ }
54
+ else {
55
+ iv = generateIv(enc);
56
+ }
51
57
  switch (enc) {
52
58
  case 'A128CBC-HS256':
53
59
  case 'A192CBC-HS384':
54
60
  case 'A256CBC-HS512':
55
- if (cek instanceof Uint8Array)
61
+ if (cek instanceof Uint8Array) {
56
62
  checkCekLength(cek, parseInt(enc.slice(-3), 10));
63
+ }
57
64
  return cbcEncrypt(enc, plaintext, cek, iv, aad);
58
65
  case 'A128GCM':
59
66
  case 'A192GCM':
60
67
  case 'A256GCM':
61
- if (cek instanceof Uint8Array)
68
+ if (cek instanceof Uint8Array) {
62
69
  checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
70
+ }
63
71
  return gcmEncrypt(enc, plaintext, cek, iv, aad);
64
72
  default:
65
73
  throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlattenedEncrypt = exports.unprotected = void 0;
4
4
  const base64url_js_1 = require("../../runtime/base64url.js");
5
5
  const encrypt_js_1 = require("../../runtime/encrypt.js");
6
- const iv_js_1 = require("../../lib/iv.js");
7
6
  const encrypt_key_management_js_1 = require("../../lib/encrypt_key_management.js");
8
7
  const errors_js_1 = require("../../util/errors.js");
9
8
  const is_disjoint_js_1 = require("../../lib/is_disjoint.js");
@@ -95,15 +94,8 @@ class FlattenedEncrypt {
95
94
  throw new errors_js_1.JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
96
95
  }
97
96
  let encryptedKey;
98
- if (alg === 'dir') {
99
- if (this._cek) {
100
- throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption');
101
- }
102
- }
103
- else if (alg === 'ECDH-ES') {
104
- if (this._cek) {
105
- throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement');
106
- }
97
+ if (this._cek && (alg === 'dir' || alg === 'ECDH-ES')) {
98
+ throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
107
99
  }
108
100
  let cek;
109
101
  {
@@ -128,7 +120,6 @@ class FlattenedEncrypt {
128
120
  }
129
121
  }
130
122
  }
131
- this._iv ||= (0, iv_js_1.default)(enc);
132
123
  let additionalData;
133
124
  let protectedHeader;
134
125
  let aadMember;
@@ -145,12 +136,16 @@ class FlattenedEncrypt {
145
136
  else {
146
137
  additionalData = protectedHeader;
147
138
  }
148
- const { ciphertext, tag } = await (0, encrypt_js_1.default)(enc, this._plaintext, cek, this._iv, additionalData);
139
+ const { ciphertext, tag, iv } = await (0, encrypt_js_1.default)(enc, this._plaintext, cek, this._iv, additionalData);
149
140
  const jwe = {
150
141
  ciphertext: (0, base64url_js_1.encode)(ciphertext),
151
- iv: (0, base64url_js_1.encode)(this._iv),
152
- tag: (0, base64url_js_1.encode)(tag),
153
142
  };
143
+ if (iv) {
144
+ jwe.iv = (0, base64url_js_1.encode)(iv);
145
+ }
146
+ if (tag) {
147
+ jwe.tag = (0, base64url_js_1.encode)(tag);
148
+ }
154
149
  if (encryptedKey) {
155
150
  jwe.encrypted_key = (0, base64url_js_1.encode)(encryptedKey);
156
151
  }
@@ -12,7 +12,7 @@ function isCloudflareWorkers() {
12
12
  let USER_AGENT;
13
13
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
14
14
  const NAME = 'jose';
15
- const VERSION = 'v5.2.2';
15
+ const VERSION = 'v5.2.3';
16
16
  USER_AGENT = `${NAME}/${VERSION}`;
17
17
  }
18
18
  class RemoteJWKSet extends local_js_1.LocalJWKSet {
@@ -3,13 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.unwrap = exports.wrap = void 0;
4
4
  const encrypt_js_1 = require("../runtime/encrypt.js");
5
5
  const decrypt_js_1 = require("../runtime/decrypt.js");
6
- const iv_js_1 = require("./iv.js");
7
6
  const base64url_js_1 = require("../runtime/base64url.js");
8
7
  async function wrap(alg, key, cek, iv) {
9
8
  const jweAlgorithm = alg.slice(0, 7);
10
- iv ||= (0, iv_js_1.default)(jweAlgorithm);
11
- const { ciphertext: encryptedKey, tag } = await (0, encrypt_js_1.default)(jweAlgorithm, cek, key, iv, new Uint8Array(0));
12
- return { encryptedKey, iv: (0, base64url_js_1.encode)(iv), tag: (0, base64url_js_1.encode)(tag) };
9
+ const wrapped = await (0, encrypt_js_1.default)(jweAlgorithm, cek, key, iv, new Uint8Array(0));
10
+ return {
11
+ encryptedKey: wrapped.ciphertext,
12
+ iv: (0, base64url_js_1.encode)(wrapped.iv),
13
+ tag: (0, base64url_js_1.encode)(wrapped.tag),
14
+ };
13
15
  }
14
16
  exports.wrap = wrap;
15
17
  async function unwrap(alg, key, encryptedKey, iv, tag) {
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const errors_js_1 = require("../util/errors.js");
4
4
  function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
5
- if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) {
5
+ if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
6
6
  throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
7
7
  }
8
8
  if (!protectedHeader || protectedHeader.crit === undefined) {
@@ -9,6 +9,7 @@ const webcrypto_js_1 = require("./webcrypto.js");
9
9
  const crypto_key_js_1 = require("../lib/crypto_key.js");
10
10
  const is_key_object_js_1 = require("./is_key_object.js");
11
11
  const invalid_key_input_js_1 = require("../lib/invalid_key_input.js");
12
+ const iv_js_1 = require("../lib/iv.js");
12
13
  const errors_js_1 = require("../util/errors.js");
13
14
  const ciphers_js_1 = require("./ciphers.js");
14
15
  const is_key_like_js_1 = require("./is_key_like.js");
@@ -27,7 +28,7 @@ function cbcEncrypt(enc, plaintext, cek, iv, aad) {
27
28
  const ciphertext = (0, buffer_utils_js_1.concat)(cipher.update(plaintext), cipher.final());
28
29
  const macSize = parseInt(enc.slice(-3), 10);
29
30
  const tag = (0, cbc_tag_js_1.default)(aad, iv, ciphertext, macSize, macKey, keySize);
30
- return { ciphertext, tag };
31
+ return { ciphertext, tag, iv };
31
32
  }
32
33
  function gcmEncrypt(enc, plaintext, cek, iv, aad) {
33
34
  const keySize = parseInt(enc.slice(1, 4), 10);
@@ -42,7 +43,7 @@ function gcmEncrypt(enc, plaintext, cek, iv, aad) {
42
43
  const ciphertext = cipher.update(plaintext);
43
44
  cipher.final();
44
45
  const tag = cipher.getAuthTag();
45
- return { ciphertext, tag };
46
+ return { ciphertext, tag, iv };
46
47
  }
47
48
  const encrypt = (enc, plaintext, cek, iv, aad) => {
48
49
  let key;
@@ -57,7 +58,12 @@ const encrypt = (enc, plaintext, cek, iv, aad) => {
57
58
  throw new TypeError((0, invalid_key_input_js_1.default)(cek, ...is_key_like_js_1.types, 'Uint8Array'));
58
59
  }
59
60
  (0, check_cek_length_js_1.default)(enc, key);
60
- (0, check_iv_length_js_1.default)(enc, iv);
61
+ if (iv) {
62
+ (0, check_iv_length_js_1.default)(enc, iv);
63
+ }
64
+ else {
65
+ iv = (0, iv_js_1.default)(enc);
66
+ }
61
67
  switch (enc) {
62
68
  case 'A128CBC-HS256':
63
69
  case 'A192CBC-HS384':
@@ -1,6 +1,5 @@
1
1
  import { encode as base64url } from '../../runtime/base64url.js';
2
2
  import encrypt from '../../runtime/encrypt.js';
3
- import generateIv from '../../lib/iv.js';
4
3
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
5
4
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
6
5
  import isDisjoint from '../../lib/is_disjoint.js';
@@ -92,15 +91,8 @@ export class FlattenedEncrypt {
92
91
  throw new JWEInvalid('JWE "enc" (Encryption Algorithm) Header Parameter missing or invalid');
93
92
  }
94
93
  let encryptedKey;
95
- if (alg === 'dir') {
96
- if (this._cek) {
97
- throw new TypeError('setContentEncryptionKey cannot be called when using Direct Encryption');
98
- }
99
- }
100
- else if (alg === 'ECDH-ES') {
101
- if (this._cek) {
102
- throw new TypeError('setContentEncryptionKey cannot be called when using Direct Key Agreement');
103
- }
94
+ if (this._cek && (alg === 'dir' || alg === 'ECDH-ES')) {
95
+ throw new TypeError(`setContentEncryptionKey cannot be called with JWE "alg" (Algorithm) Header ${alg}`);
104
96
  }
105
97
  let cek;
106
98
  {
@@ -125,7 +117,6 @@ export class FlattenedEncrypt {
125
117
  }
126
118
  }
127
119
  }
128
- this._iv ||= generateIv(enc);
129
120
  let additionalData;
130
121
  let protectedHeader;
131
122
  let aadMember;
@@ -142,12 +133,16 @@ export class FlattenedEncrypt {
142
133
  else {
143
134
  additionalData = protectedHeader;
144
135
  }
145
- const { ciphertext, tag } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData);
136
+ const { ciphertext, tag, iv } = await encrypt(enc, this._plaintext, cek, this._iv, additionalData);
146
137
  const jwe = {
147
138
  ciphertext: base64url(ciphertext),
148
- iv: base64url(this._iv),
149
- tag: base64url(tag),
150
139
  };
140
+ if (iv) {
141
+ jwe.iv = base64url(iv);
142
+ }
143
+ if (tag) {
144
+ jwe.tag = base64url(tag);
145
+ }
151
146
  if (encryptedKey) {
152
147
  jwe.encrypted_key = base64url(encryptedKey);
153
148
  }
@@ -9,7 +9,7 @@ function isCloudflareWorkers() {
9
9
  let USER_AGENT;
10
10
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
11
11
  const NAME = 'jose';
12
- const VERSION = 'v5.2.2';
12
+ const VERSION = 'v5.2.3';
13
13
  USER_AGENT = `${NAME}/${VERSION}`;
14
14
  }
15
15
  class RemoteJWKSet extends LocalJWKSet {
@@ -1,12 +1,14 @@
1
1
  import encrypt from '../runtime/encrypt.js';
2
2
  import decrypt from '../runtime/decrypt.js';
3
- import generateIv from './iv.js';
4
3
  import { encode as base64url } from '../runtime/base64url.js';
5
4
  export async function wrap(alg, key, cek, iv) {
6
5
  const jweAlgorithm = alg.slice(0, 7);
7
- iv ||= generateIv(jweAlgorithm);
8
- const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
9
- return { encryptedKey, iv: base64url(iv), tag: base64url(tag) };
6
+ const wrapped = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
7
+ return {
8
+ encryptedKey: wrapped.ciphertext,
9
+ iv: base64url(wrapped.iv),
10
+ tag: base64url(wrapped.tag),
11
+ };
10
12
  }
11
13
  export async function unwrap(alg, key, encryptedKey, iv, tag) {
12
14
  const jweAlgorithm = alg.slice(0, 7);
@@ -1,6 +1,6 @@
1
1
  import { JOSENotSupported } from '../util/errors.js';
2
2
  function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
3
- if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) {
3
+ if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {
4
4
  throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
5
5
  }
6
6
  if (!protectedHeader || protectedHeader.crit === undefined) {
@@ -7,6 +7,7 @@ import { isCryptoKey } from './webcrypto.js';
7
7
  import { checkEncCryptoKey } from '../lib/crypto_key.js';
8
8
  import isKeyObject from './is_key_object.js';
9
9
  import invalidKeyInput from '../lib/invalid_key_input.js';
10
+ import generateIv from '../lib/iv.js';
10
11
  import { JOSENotSupported } from '../util/errors.js';
11
12
  import supported from './ciphers.js';
12
13
  import { types } from './is_key_like.js';
@@ -25,7 +26,7 @@ function cbcEncrypt(enc, plaintext, cek, iv, aad) {
25
26
  const ciphertext = concat(cipher.update(plaintext), cipher.final());
26
27
  const macSize = parseInt(enc.slice(-3), 10);
27
28
  const tag = cbcTag(aad, iv, ciphertext, macSize, macKey, keySize);
28
- return { ciphertext, tag };
29
+ return { ciphertext, tag, iv };
29
30
  }
30
31
  function gcmEncrypt(enc, plaintext, cek, iv, aad) {
31
32
  const keySize = parseInt(enc.slice(1, 4), 10);
@@ -40,7 +41,7 @@ function gcmEncrypt(enc, plaintext, cek, iv, aad) {
40
41
  const ciphertext = cipher.update(plaintext);
41
42
  cipher.final();
42
43
  const tag = cipher.getAuthTag();
43
- return { ciphertext, tag };
44
+ return { ciphertext, tag, iv };
44
45
  }
45
46
  const encrypt = (enc, plaintext, cek, iv, aad) => {
46
47
  let key;
@@ -55,7 +56,12 @@ const encrypt = (enc, plaintext, cek, iv, aad) => {
55
56
  throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array'));
56
57
  }
57
58
  checkCekLength(enc, key);
58
- checkIvLength(enc, iv);
59
+ if (iv) {
60
+ checkIvLength(enc, iv);
61
+ }
62
+ else {
63
+ iv = generateIv(enc);
64
+ }
59
65
  switch (enc) {
60
66
  case 'A128CBC-HS256':
61
67
  case 'A192CBC-HS384':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jose",
3
- "version": "5.2.2",
3
+ "version": "5.2.3",
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
6
  "browser",