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
@@ -1,13 +1,13 @@
1
- import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js';
2
- import isDisjoint from '../../lib/is_disjoint.js';
3
- import isObject from '../../lib/is_object.js';
4
1
  import { decode as base64url } from '../../runtime/base64url.js';
5
2
  import decrypt from '../../runtime/decrypt.js';
6
3
  import { inflate } from '../../runtime/zlib.js';
4
+ import random from '../../runtime/random.js';
5
+ import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js';
6
+ import isDisjoint from '../../lib/is_disjoint.js';
7
+ import isObject from '../../lib/is_object.js';
7
8
  import decryptKeyManagement from '../../lib/decrypt_key_management.js';
8
9
  import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
9
10
  import cekFactory from '../../lib/cek.js';
10
- import random from '../../runtime/random.js';
11
11
  import validateCrit from '../../lib/validate_crit.js';
12
12
  import validateAlgorithms from '../../lib/validate_algorithms.js';
13
13
  const generateCek = cekFactory(random);
@@ -70,7 +70,7 @@ async function flattenedDecrypt(jwe, key, options) {
70
70
  throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
71
71
  }
72
72
  if (joseHeader.zip !== 'DEF') {
73
- throw new JOSENotSupported('unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
73
+ throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
74
74
  }
75
75
  }
76
76
  const { alg, enc } = joseHeader;
@@ -92,8 +92,10 @@ async function flattenedDecrypt(jwe, key, options) {
92
92
  if (jwe.encrypted_key !== undefined) {
93
93
  encryptedKey = base64url(jwe.encrypted_key);
94
94
  }
95
+ let resolvedKey = false;
95
96
  if (typeof key === 'function') {
96
97
  key = await key(parsedProt, jwe);
98
+ resolvedKey = true;
97
99
  }
98
100
  let cek;
99
101
  try {
@@ -132,6 +134,9 @@ async function flattenedDecrypt(jwe, key, options) {
132
134
  if (jwe.header !== undefined) {
133
135
  result.unprotectedHeader = jwe.header;
134
136
  }
137
+ if (resolvedKey) {
138
+ return { ...result, key };
139
+ }
135
140
  return result;
136
141
  }
137
142
  export { flattenedDecrypt };
@@ -1,8 +1,8 @@
1
- import ivFactory from '../../lib/iv.js';
2
1
  import { encode as base64url } from '../../runtime/base64url.js';
3
2
  import random from '../../runtime/random.js';
4
3
  import encrypt from '../../runtime/encrypt.js';
5
4
  import { deflate } from '../../runtime/zlib.js';
5
+ import ivFactory from '../../lib/iv.js';
6
6
  import encryptKeyManagement from '../../lib/encrypt_key_management.js';
7
7
  import { JOSENotSupported, JWEInvalid } from '../../util/errors.js';
8
8
  import isDisjoint from '../../lib/is_disjoint.js';
@@ -12,6 +12,9 @@ const generateIv = ivFactory(random);
12
12
  const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map());
13
13
  class FlattenedEncrypt {
14
14
  constructor(plaintext) {
15
+ if (!(plaintext instanceof Uint8Array)) {
16
+ throw new TypeError('plaintext must be an instance of Uint8Array');
17
+ }
15
18
  this._plaintext = plaintext;
16
19
  }
17
20
  setKeyManagementParameters(parameters) {
@@ -78,7 +81,7 @@ class FlattenedEncrypt {
78
81
  throw new JWEInvalid('JWE "zip" (Compression Algorithm) Header MUST be integrity protected');
79
82
  }
80
83
  if (joseHeader.zip !== 'DEF') {
81
- throw new JOSENotSupported('unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
84
+ throw new JOSENotSupported('Unsupported JWE "zip" (Compression Algorithm) Header Parameter value');
82
85
  }
83
86
  }
84
87
  const { alg, enc } = joseHeader;
@@ -1,4 +1,4 @@
1
- import parseJwk from './parse.js';
1
+ import { importJWK } from '../key/import.js';
2
2
  import isObject from '../lib/is_object.js';
3
3
  import { JWSInvalid } from '../util/errors.js';
4
4
  async function EmbeddedJWK(protectedHeader, token) {
@@ -9,7 +9,7 @@ async function EmbeddedJWK(protectedHeader, token) {
9
9
  if (!isObject(joseHeader.jwk)) {
10
10
  throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a JSON object');
11
11
  }
12
- const key = await parseJwk(joseHeader.jwk, joseHeader.alg, true);
12
+ const key = (await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true));
13
13
  if (key.type !== 'public') {
14
14
  throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');
15
15
  }
@@ -1,6 +1,6 @@
1
- import asJWK from '../runtime/key_to_jwk.js';
1
+ import { exportJWK } from '../key/export.js';
2
2
  async function fromKeyLike(key) {
3
- return asJWK(key);
3
+ return exportJWK(key);
4
4
  }
5
5
  export { fromKeyLike };
6
6
  export default fromKeyLike;
@@ -1,35 +1,6 @@
1
- import { decode as base64url } from '../runtime/base64url.js';
2
- import asKeyObject from '../runtime/jwk_to_key.js';
3
- import { JOSENotSupported } from '../util/errors.js';
4
- import isObject from '../lib/is_object.js';
1
+ import { importJWK } from '../key/import.js';
5
2
  async function parseJwk(jwk, alg, octAsKeyObject) {
6
- if (!isObject(jwk)) {
7
- throw new TypeError('JWK must be an object');
8
- }
9
- alg || (alg = jwk.alg);
10
- if (typeof alg !== 'string' || !alg) {
11
- throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
12
- }
13
- switch (jwk.kty) {
14
- case 'oct':
15
- if (typeof jwk.k !== 'string' || !jwk.k) {
16
- throw new TypeError('missing "k" (Key Value) Parameter value');
17
- }
18
- octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true);
19
- if (octAsKeyObject) {
20
- return asKeyObject({ ...jwk, alg, ext: false });
21
- }
22
- return base64url(jwk.k);
23
- case 'RSA':
24
- if (jwk.oth !== undefined) {
25
- throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
26
- }
27
- case 'EC':
28
- case 'OKP':
29
- return asKeyObject({ ...jwk, alg });
30
- default:
31
- throw new JOSENotSupported('unsupported "kty" (Key Type) Parameter value');
32
- }
3
+ return importJWK(jwk, alg, octAsKeyObject);
33
4
  }
34
5
  export { parseJwk };
35
6
  export default parseJwk;
@@ -1,6 +1,6 @@
1
- import { JOSENotSupported, JWKInvalid } from '../util/errors.js';
2
1
  import digest from '../runtime/digest.js';
3
2
  import { encode as base64url } from '../runtime/base64url.js';
3
+ import { JOSENotSupported, JWKInvalid } from '../util/errors.js';
4
4
  import { encoder } from '../lib/buffer_utils.js';
5
5
  import isObject from '../lib/is_object.js';
6
6
  const check = (value, description) => {
@@ -1,6 +1,6 @@
1
+ import fetchJwks from '../runtime/fetch_jwks.js';
1
2
  import parseJWK from '../jwk/parse.js';
2
3
  import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';
3
- import fetchJwks from '../runtime/fetch_jwks.js';
4
4
  import isObject from '../lib/is_object.js';
5
5
  function getKtyFromAlg(alg) {
6
6
  switch (alg.substr(0, 2)) {
@@ -93,7 +93,7 @@ class RemoteJWKSet {
93
93
  }
94
94
  const cached = this._cached.get(jwk);
95
95
  if (cached[protectedHeader.alg] === undefined) {
96
- const keyObject = await parseJWK({ ...jwk, alg: protectedHeader.alg });
96
+ const keyObject = (await parseJWK({ ...jwk, alg: protectedHeader.alg, ext: true }));
97
97
  if (keyObject.type !== 'public') {
98
98
  throw new JWKSInvalid('JSON Web Key Set members must be public keys');
99
99
  }
@@ -17,7 +17,11 @@ async function compactVerify(jws, key, options) {
17
17
  protected: protectedHeader || undefined,
18
18
  signature: (signature || undefined),
19
19
  }, key, options);
20
- return { payload: verified.payload, protectedHeader: verified.protectedHeader };
20
+ const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };
21
+ if (typeof key === 'function') {
22
+ return { ...result, key: verified.key };
23
+ }
24
+ return result;
21
25
  }
22
26
  export { compactVerify };
23
27
  export default compactVerify;
@@ -1,13 +1,16 @@
1
+ import { encode as base64url } from '../../runtime/base64url.js';
2
+ import sign from '../../runtime/sign.js';
1
3
  import isDisjoint from '../../lib/is_disjoint.js';
2
4
  import { JWSInvalid } from '../../util/errors.js';
3
5
  import { encoder, decoder, concat } from '../../lib/buffer_utils.js';
4
- import { encode as base64url } from '../../runtime/base64url.js';
5
- import sign from '../../runtime/sign.js';
6
6
  import checkKeyType from '../../lib/check_key_type.js';
7
7
  import validateCrit from '../../lib/validate_crit.js';
8
8
  const checkExtensions = validateCrit.bind(undefined, JWSInvalid, new Map([['b64', true]]));
9
9
  class FlattenedSign {
10
10
  constructor(payload) {
11
+ if (!(payload instanceof Uint8Array)) {
12
+ throw new TypeError('payload must be an instance of Uint8Array');
13
+ }
11
14
  this._payload = payload;
12
15
  }
13
16
  setProtectedHeader(protectedHeader) {
@@ -1,10 +1,10 @@
1
+ import { decode as base64url } from '../../runtime/base64url.js';
2
+ import verify from '../../runtime/verify.js';
1
3
  import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';
2
4
  import { concat, encoder, decoder } from '../../lib/buffer_utils.js';
3
5
  import isDisjoint from '../../lib/is_disjoint.js';
4
6
  import isObject from '../../lib/is_object.js';
5
7
  import checkKeyType from '../../lib/check_key_type.js';
6
- import { decode as base64url } from '../../runtime/base64url.js';
7
- import verify from '../../runtime/verify.js';
8
8
  import validateCrit from '../../lib/validate_crit.js';
9
9
  import validateAlgorithms from '../../lib/validate_algorithms.js';
10
10
  const checkExtensions = validateCrit.bind(undefined, JWSInvalid, new Map([['b64', true]]));
@@ -70,8 +70,10 @@ async function flattenedVerify(jws, key, options) {
70
70
  else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {
71
71
  throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');
72
72
  }
73
+ let resolvedKey = false;
73
74
  if (typeof key === 'function') {
74
75
  key = await key(parsedProt, jws);
76
+ resolvedKey = true;
75
77
  }
76
78
  checkKeyType(alg, key, 'verify');
77
79
  const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);
@@ -97,6 +99,9 @@ async function flattenedVerify(jws, key, options) {
97
99
  if (jws.header !== undefined) {
98
100
  result.unprotectedHeader = jws.header;
99
101
  }
102
+ if (resolvedKey) {
103
+ return { ...result, key };
104
+ }
100
105
  return result;
101
106
  }
102
107
  export { flattenedVerify };
@@ -15,7 +15,11 @@ async function jwtDecrypt(jwt, key, options) {
15
15
  JSON.stringify(protectedHeader.aud) !== JSON.stringify(payload.aud)) {
16
16
  throw new JWTClaimValidationFailed('replicated "aud" claim header parameter mismatch', 'aud', 'mismatch');
17
17
  }
18
- return { payload, protectedHeader };
18
+ const result = { payload, protectedHeader };
19
+ if (typeof key === 'function') {
20
+ return { ...result, key: decrypted.key };
21
+ }
22
+ return result;
19
23
  }
20
24
  export { jwtDecrypt };
21
25
  export default jwtDecrypt;
@@ -1,5 +1,5 @@
1
- import { decoder } from '../lib/buffer_utils.js';
2
1
  import * as base64url from '../runtime/base64url.js';
2
+ import { decoder } from '../lib/buffer_utils.js';
3
3
  import { JWTInvalid } from '../util/errors.js';
4
4
  import jwtPayload from '../lib/jwt_claims_set.js';
5
5
  import ProduceJWT from '../lib/jwt_producer.js';
@@ -8,7 +8,11 @@ async function jwtVerify(jwt, key, options) {
8
8
  throw new JWTInvalid('JWTs MUST NOT use unencoded payload');
9
9
  }
10
10
  const payload = jwtPayload(verified.protectedHeader, verified.payload, options);
11
- return { payload, protectedHeader: verified.protectedHeader };
11
+ const result = { payload, protectedHeader: verified.protectedHeader };
12
+ if (typeof key === 'function') {
13
+ return { ...result, key: verified.key };
14
+ }
15
+ return result;
12
16
  }
13
17
  export { jwtVerify };
14
18
  export default jwtVerify;
@@ -0,0 +1,12 @@
1
+ import { toSPKI as exportPublic } from '../runtime/asn1.js';
2
+ import { toPKCS8 as exportPrivate } from '../runtime/asn1.js';
3
+ import keyToJWK from '../runtime/key_to_jwk.js';
4
+ export async function exportSPKI(key) {
5
+ return exportPublic(key);
6
+ }
7
+ export async function exportPKCS8(key) {
8
+ return exportPrivate(key);
9
+ }
10
+ export async function exportJWK(key) {
11
+ return keyToJWK(key);
12
+ }
@@ -0,0 +1,119 @@
1
+ import { decode as decodeBase64URL, encodeBase64, decodeBase64 } from '../runtime/base64url.js';
2
+ import { fromSPKI as importPublic } from '../runtime/asn1.js';
3
+ import { fromPKCS8 as importPrivate } from '../runtime/asn1.js';
4
+ import asKeyObject from '../runtime/jwk_to_key.js';
5
+ import { JOSENotSupported } from '../util/errors.js';
6
+ import formatPEM from '../lib/format_pem.js';
7
+ import isObject from '../lib/is_object.js';
8
+ function getElement(seq) {
9
+ let result = [];
10
+ let next = 0;
11
+ while (next < seq.length) {
12
+ let nextPart = parseElement(seq.subarray(next));
13
+ result.push(nextPart);
14
+ next += nextPart.byteLength;
15
+ }
16
+ return result;
17
+ }
18
+ function parseElement(bytes) {
19
+ let position = 0;
20
+ let tag = bytes[0] & 0x1f;
21
+ position++;
22
+ if (tag === 0x1f) {
23
+ tag = 0;
24
+ while (bytes[position] >= 0x80) {
25
+ tag = tag * 128 + bytes[position] - 0x80;
26
+ position++;
27
+ }
28
+ tag = tag * 128 + bytes[position] - 0x80;
29
+ position++;
30
+ }
31
+ let length = 0;
32
+ if (bytes[position] < 0x80) {
33
+ length = bytes[position];
34
+ position++;
35
+ }
36
+ else {
37
+ let numberOfDigits = bytes[position] & 0x7f;
38
+ position++;
39
+ length = 0;
40
+ for (let i = 0; i < numberOfDigits; i++) {
41
+ length = length * 256 + bytes[position];
42
+ position++;
43
+ }
44
+ }
45
+ if (length === 0x80) {
46
+ length = 0;
47
+ while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) {
48
+ length++;
49
+ }
50
+ const byteLength = position + length + 2;
51
+ return {
52
+ byteLength,
53
+ contents: bytes.subarray(position, position + length),
54
+ raw: bytes.subarray(0, byteLength),
55
+ };
56
+ }
57
+ const byteLength = position + length;
58
+ return {
59
+ byteLength,
60
+ contents: bytes.subarray(position, byteLength),
61
+ raw: bytes.subarray(0, byteLength),
62
+ };
63
+ }
64
+ function spkiFromX509(buf) {
65
+ return encodeBase64(getElement(getElement(parseElement(buf).contents)[0].contents)[6].raw);
66
+ }
67
+ function getSPKI(x509) {
68
+ const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '');
69
+ const raw = decodeBase64(pem);
70
+ return formatPEM(spkiFromX509(raw), 'PUBLIC KEY');
71
+ }
72
+ export async function importSPKI(spki, alg, options) {
73
+ if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {
74
+ throw new TypeError('"spki" must be SPKI formatted string');
75
+ }
76
+ return importPublic(spki, alg, options);
77
+ }
78
+ export async function importX509(x509, alg, options) {
79
+ if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {
80
+ throw new TypeError('"x509" must be X.509 formatted string');
81
+ }
82
+ const spki = getSPKI(x509);
83
+ return importPublic(spki, alg, options);
84
+ }
85
+ export async function importPKCS8(pkcs8, alg, options) {
86
+ if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {
87
+ throw new TypeError('"pkcs8" must be PCKS8 formatted string');
88
+ }
89
+ return importPrivate(pkcs8, alg, options);
90
+ }
91
+ export async function importJWK(jwk, alg, octAsKeyObject) {
92
+ if (!isObject(jwk)) {
93
+ throw new TypeError('JWK must be an object');
94
+ }
95
+ alg || (alg = jwk.alg);
96
+ if (typeof alg !== 'string' || !alg) {
97
+ throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
98
+ }
99
+ switch (jwk.kty) {
100
+ case 'oct':
101
+ if (typeof jwk.k !== 'string' || !jwk.k) {
102
+ throw new TypeError('missing "k" (Key Value) Parameter value');
103
+ }
104
+ octAsKeyObject !== null && octAsKeyObject !== void 0 ? octAsKeyObject : (octAsKeyObject = jwk.ext !== true);
105
+ if (octAsKeyObject) {
106
+ return asKeyObject({ ...jwk, alg, ext: false });
107
+ }
108
+ return decodeBase64URL(jwk.k);
109
+ case 'RSA':
110
+ if (jwk.oth !== undefined) {
111
+ throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
112
+ }
113
+ case 'EC':
114
+ case 'OKP':
115
+ return asKeyObject({ ...jwk, alg });
116
+ default:
117
+ throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
118
+ }
119
+ }
@@ -1,12 +1,12 @@
1
- import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
2
1
  import { unwrap as aesKw } from '../runtime/aeskw.js';
3
2
  import * as ECDH from '../runtime/ecdhes.js';
4
3
  import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js';
5
4
  import { decrypt as rsaEs } from '../runtime/rsaes.js';
6
5
  import { unwrap as aesGcmKw } from '../runtime/aesgcmkw.js';
7
6
  import { decode as base64url } from '../runtime/base64url.js';
7
+ import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
8
8
  import { bitLengths as cekLengths } from '../lib/cek.js';
9
- import { parseJwk } from '../jwk/parse.js';
9
+ import { importJWK } from '../key/import.js';
10
10
  import checkKeyType from './check_key_type.js';
11
11
  function assertEnryptedKey(encryptedKey) {
12
12
  if (!encryptedKey) {
@@ -38,7 +38,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
38
38
  if (!ECDH.ecdhAllowed(key)) {
39
39
  throw new JOSENotSupported('ECDH-ES with the provided key is not allowed or not supported by your javascript runtime');
40
40
  }
41
- const epk = await parseJwk(joseHeader.epk, alg);
41
+ const epk = await importJWK(joseHeader.epk, alg);
42
42
  let partyUInfo;
43
43
  let partyVInfo;
44
44
  if (joseHeader.apu !== undefined)
@@ -88,7 +88,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
88
88
  return aesGcmKw(alg, key, encryptedKey, iv, tag);
89
89
  }
90
90
  default: {
91
- throw new JOSENotSupported('unsupported or invalid "alg" (JWE Algorithm) header value');
91
+ throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
92
92
  }
93
93
  }
94
94
  }
@@ -1,5 +1,3 @@
1
- import cekFactory, { bitLengths as cekLengths } from '../lib/cek.js';
2
- import { JOSENotSupported } from '../util/errors.js';
3
1
  import random from '../runtime/random.js';
4
2
  import { wrap as aesKw } from '../runtime/aeskw.js';
5
3
  import * as ECDH from '../runtime/ecdhes.js';
@@ -7,6 +5,8 @@ import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js';
7
5
  import { encrypt as rsaEs } from '../runtime/rsaes.js';
8
6
  import { wrap as aesGcmKw } from '../runtime/aesgcmkw.js';
9
7
  import { encode as base64url } from '../runtime/base64url.js';
8
+ import cekFactory, { bitLengths as cekLengths } from '../lib/cek.js';
9
+ import { JOSENotSupported } from '../util/errors.js';
10
10
  import { fromKeyLike } from '../jwk/from_key_like.js';
11
11
  import checkKeyType from './check_key_type.js';
12
12
  const generateCek = cekFactory(random);
@@ -79,7 +79,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
79
79
  break;
80
80
  }
81
81
  default: {
82
- throw new JOSENotSupported('unsupported or invalid "alg" (JWE Algorithm) header value');
82
+ throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
83
83
  }
84
84
  }
85
85
  return { cek, encryptedKey, parameters };
@@ -0,0 +1,4 @@
1
+ export default (b64, descriptor) => {
2
+ const newlined = (b64.match(/.{1,64}/g) || []).join('\n');
3
+ return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----`;
4
+ };
@@ -8,7 +8,7 @@ import invalidKeyInput from './invalid_key_input.js';
8
8
  import supported from './ciphers.js';
9
9
  function checkKeySize(key, alg) {
10
10
  if (key.symmetricKeySize << 3 !== parseInt(alg.substr(1, 3), 10)) {
11
- throw new TypeError(`invalid key size for alg: ${alg}`);
11
+ throw new TypeError(`Invalid key size for alg: ${alg}`);
12
12
  }
13
13
  }
14
14
  function ensureKeyObject(key, alg, usage) {
@@ -0,0 +1,39 @@
1
+ import { createPrivateKey, createPublicKey } from 'crypto';
2
+ import { isCryptoKey, getKeyObject } from './webcrypto.js';
3
+ import isKeyObject from './is_key_object.js';
4
+ import invalidKeyInput from './invalid_key_input.js';
5
+ const genericExport = (keyType, keyFormat, key) => {
6
+ let keyObject;
7
+ if (isCryptoKey(key)) {
8
+ if (!key.extractable) {
9
+ throw new TypeError('CryptoKey is not extractable');
10
+ }
11
+ keyObject = getKeyObject(key);
12
+ }
13
+ else if (isKeyObject(key)) {
14
+ keyObject = key;
15
+ }
16
+ else {
17
+ throw new TypeError(invalidKeyInput(key, 'KeyObject', 'CryptoKey'));
18
+ }
19
+ if (keyObject.type !== keyType) {
20
+ throw new TypeError(`key is not a ${keyType} key`);
21
+ }
22
+ return keyObject.export({ format: 'pem', type: keyFormat });
23
+ };
24
+ export const toSPKI = (key) => {
25
+ return genericExport('public', 'spki', key);
26
+ };
27
+ export const toPKCS8 = (key) => {
28
+ return genericExport('private', 'pkcs8', key);
29
+ };
30
+ export const fromPKCS8 = (pem) => createPrivateKey({
31
+ key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'),
32
+ type: 'pkcs8',
33
+ format: 'der',
34
+ });
35
+ export const fromSPKI = (pem) => createPublicKey({
36
+ key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'),
37
+ type: 'spki',
38
+ format: 'der',
39
+ });
@@ -38,7 +38,7 @@ export default class DumbAsn1Encoder {
38
38
  oidFor(oid) {
39
39
  const bOid = oids.get(oid);
40
40
  if (!bOid) {
41
- throw new JOSENotSupported('unsupported or invalid OID');
41
+ throw new JOSENotSupported('Invalid or unsupported OID');
42
42
  }
43
43
  this.elements.push(bOid);
44
44
  this.length += bOid.length;
@@ -13,5 +13,7 @@ if (Buffer.isEncoding('base64url')) {
13
13
  else {
14
14
  encodeImpl = (input) => Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
15
15
  }
16
+ export const decodeBase64 = (input) => Buffer.from(input, 'base64');
17
+ export const encodeBase64 = (input) => Buffer.from(input).toString('base64');
16
18
  export const encode = encodeImpl;
17
19
  export const decode = (input) => Buffer.from(normalize(input), 'base64');
@@ -84,7 +84,7 @@ const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
84
84
  case 'A256GCM':
85
85
  return gcmDecrypt(enc, key, ciphertext, iv, tag, aad);
86
86
  default:
87
- throw new JOSENotSupported('unsupported JWE Content Encryption Algorithm');
87
+ throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
88
88
  }
89
89
  };
90
90
  export default decrypt;
@@ -8,29 +8,41 @@ import { isCryptoKey, getKeyObject } from './webcrypto.js';
8
8
  import isKeyObject from './is_key_object.js';
9
9
  import invalidKeyInput from './invalid_key_input.js';
10
10
  const generateKeyPair = promisify(generateKeyPairCb);
11
- export const deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
12
- const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
13
- if (isCryptoKey(publicKey)) {
14
- publicKey = getKeyObject(publicKey, 'ECDH-ES');
11
+ export const deriveKey = async (publicKee, privateKee, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) => {
12
+ let publicKey;
13
+ if (isCryptoKey(publicKee)) {
14
+ publicKey = getKeyObject(publicKee, 'ECDH-ES');
15
+ }
16
+ else if (isKeyObject(publicKee)) {
17
+ publicKey = publicKee;
18
+ }
19
+ else {
20
+ throw new TypeError(invalidKeyInput(publicKee, 'KeyObject', 'CryptoKey'));
15
21
  }
16
- if (!isKeyObject(publicKey)) {
17
- throw new TypeError(invalidKeyInput(publicKey, 'KeyObject', 'CryptoKey'));
22
+ let privateKey;
23
+ if (isCryptoKey(privateKee)) {
24
+ privateKey = getKeyObject(privateKee, 'ECDH-ES', new Set(['deriveBits', 'deriveKey']));
18
25
  }
19
- if (isCryptoKey(privateKey)) {
20
- privateKey = getKeyObject(privateKey, 'ECDH-ES', new Set(['deriveBits', 'deriveKey']));
26
+ else if (isKeyObject(privateKee)) {
27
+ privateKey = privateKee;
21
28
  }
22
- if (!isKeyObject(privateKey)) {
23
- throw new TypeError(invalidKeyInput(privateKey, 'KeyObject', 'CryptoKey'));
29
+ else {
30
+ throw new TypeError(invalidKeyInput(privateKee, 'KeyObject', 'CryptoKey'));
24
31
  }
32
+ const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength));
25
33
  const sharedSecret = diffieHellman({ privateKey, publicKey });
26
34
  return concatKdf(digest, sharedSecret, keyLength, value);
27
35
  };
28
- export const generateEpk = async (key) => {
29
- if (isCryptoKey(key)) {
30
- key = getKeyObject(key);
36
+ export const generateEpk = async (kee) => {
37
+ let key;
38
+ if (isCryptoKey(kee)) {
39
+ key = getKeyObject(kee);
40
+ }
41
+ else if (isKeyObject(kee)) {
42
+ key = kee;
31
43
  }
32
- if (!isKeyObject(key)) {
33
- throw new TypeError(invalidKeyInput(key, 'KeyObject', 'CryptoKey'));
44
+ else {
45
+ throw new TypeError(invalidKeyInput(kee, 'KeyObject', 'CryptoKey'));
34
46
  }
35
47
  switch (key.asymmetricKeyType) {
36
48
  case 'x25519':
@@ -43,7 +55,7 @@ export const generateEpk = async (key) => {
43
55
  return (await generateKeyPair('ec', { namedCurve })).privateKey;
44
56
  }
45
57
  default:
46
- throw new JOSENotSupported('unsupported or invalid EPK');
58
+ throw new JOSENotSupported('Invalid or unsupported EPK');
47
59
  }
48
60
  };
49
61
  export const ecdhAllowed = (key) => ['P-256', 'P-384', 'P-521', 'X25519', 'X448'].includes(getNamedCurve(key));
@@ -62,7 +62,7 @@ const encrypt = async (enc, plaintext, cek, iv, aad) => {
62
62
  case 'A256GCM':
63
63
  return gcmEncrypt(enc, plaintext, key, iv, aad);
64
64
  default:
65
- throw new JOSENotSupported('unsupported JWE Content Encryption Algorithm');
65
+ throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
66
66
  }
67
67
  };
68
68
  export default encrypt;
@@ -27,7 +27,7 @@ export async function generateSecret(alg, options) {
27
27
  length = parseInt(alg.substring(1, 4), 10);
28
28
  break;
29
29
  default:
30
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
30
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
31
31
  }
32
32
  return createSecretKey(random(new Uint8Array(length >> 3)));
33
33
  }
@@ -94,6 +94,6 @@ export async function generateKeyPair(alg, options) {
94
94
  throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448');
95
95
  }
96
96
  default:
97
- throw new JOSENotSupported('unsupported or invalid JWK "alg" (Algorithm) Parameter value');
97
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
98
98
  }
99
99
  }