jose 3.17.0 → 3.20.1
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.
- package/README.md +10 -3
- package/dist/browser/jwe/compact/decrypt.js +5 -1
- package/dist/browser/jwe/flattened/decrypt.js +5 -0
- package/dist/browser/jwk/embedded.js +3 -3
- package/dist/browser/jwk/from_key_like.js +2 -2
- package/dist/browser/jwk/parse.js +2 -31
- package/dist/browser/jwks/remote.js +7 -10
- package/dist/browser/jws/compact/verify.js +5 -1
- package/dist/browser/jws/flattened/verify.js +5 -0
- package/dist/browser/jwt/decrypt.js +5 -1
- package/dist/browser/jwt/encrypt.js +1 -1
- package/dist/browser/{lib/jwt_producer.js → jwt/produce.js} +4 -4
- package/dist/browser/jwt/sign.js +1 -1
- package/dist/browser/jwt/unsecured.js +1 -1
- package/dist/browser/jwt/verify.js +5 -1
- package/dist/browser/key/export.js +12 -0
- package/dist/browser/key/import.js +119 -0
- package/dist/browser/lib/check_key_type.js +33 -16
- package/dist/browser/lib/decrypt_key_management.js +37 -37
- package/dist/browser/lib/encrypt_key_management.js +2 -2
- package/dist/browser/lib/format_pem.js +4 -0
- package/dist/browser/runtime/asn1.js +119 -0
- package/dist/browser/runtime/base64url.js +12 -7
- package/dist/browser/runtime/fetch_jwks.js +18 -5
- package/dist/browser/runtime/is_key_like.js +5 -0
- package/dist/browser/util/errors.js +10 -3
- package/dist/node/cjs/jwe/compact/decrypt.js +5 -1
- package/dist/node/cjs/jwe/flattened/decrypt.js +5 -0
- package/dist/node/cjs/jwk/embedded.js +3 -3
- package/dist/node/cjs/jwk/from_key_like.js +2 -2
- package/dist/node/cjs/jwk/parse.js +2 -31
- package/dist/node/cjs/jwks/remote.js +7 -10
- package/dist/node/cjs/jws/compact/verify.js +5 -1
- package/dist/node/cjs/jws/flattened/verify.js +5 -0
- package/dist/node/cjs/jwt/decrypt.js +5 -1
- package/dist/node/cjs/jwt/encrypt.js +2 -2
- package/dist/node/cjs/{lib/jwt_producer.js → jwt/produce.js} +5 -4
- package/dist/node/cjs/jwt/sign.js +2 -2
- package/dist/node/cjs/jwt/unsecured.js +2 -2
- package/dist/node/cjs/jwt/verify.js +5 -1
- package/dist/node/cjs/key/export.js +18 -0
- package/dist/node/cjs/key/import.js +126 -0
- package/dist/node/cjs/lib/check_key_type.js +33 -16
- package/dist/node/cjs/lib/decrypt_key_management.js +37 -37
- package/dist/node/cjs/lib/encrypt_key_management.js +2 -2
- package/dist/node/cjs/lib/format_pem.js +6 -0
- package/dist/node/cjs/runtime/asn1.js +46 -0
- package/dist/node/cjs/runtime/base64url.js +5 -1
- package/dist/node/cjs/runtime/fetch_jwks.js +5 -1
- package/dist/node/cjs/runtime/is_key_like.js +11 -0
- package/dist/node/cjs/util/errors.js +12 -4
- package/dist/node/esm/jwe/compact/decrypt.js +5 -1
- package/dist/node/esm/jwe/flattened/decrypt.js +5 -0
- package/dist/node/esm/jwk/embedded.js +3 -3
- package/dist/node/esm/jwk/from_key_like.js +2 -2
- package/dist/node/esm/jwk/parse.js +2 -31
- package/dist/node/esm/jwks/remote.js +7 -10
- package/dist/node/esm/jws/compact/verify.js +5 -1
- package/dist/node/esm/jws/flattened/verify.js +5 -0
- package/dist/node/esm/jwt/decrypt.js +5 -1
- package/dist/node/esm/jwt/encrypt.js +1 -1
- package/dist/node/esm/{lib/jwt_producer.js → jwt/produce.js} +4 -4
- package/dist/node/esm/jwt/sign.js +1 -1
- package/dist/node/esm/jwt/unsecured.js +1 -1
- package/dist/node/esm/jwt/verify.js +5 -1
- package/dist/node/esm/key/export.js +12 -0
- package/dist/node/esm/key/import.js +119 -0
- package/dist/node/esm/lib/check_key_type.js +33 -16
- package/dist/node/esm/lib/decrypt_key_management.js +37 -37
- package/dist/node/esm/lib/encrypt_key_management.js +2 -2
- package/dist/node/esm/lib/format_pem.js +4 -0
- package/dist/node/esm/runtime/asn1.js +39 -0
- package/dist/node/esm/runtime/base64url.js +2 -0
- package/dist/node/esm/runtime/fetch_jwks.js +6 -2
- package/dist/node/esm/runtime/is_key_like.js +8 -0
- package/dist/node/esm/util/errors.js +10 -3
- package/dist/types/jwe/compact/decrypt.d.ts +3 -2
- package/dist/types/jwe/compact/encrypt.d.ts +1 -1
- package/dist/types/jwe/flattened/decrypt.d.ts +3 -2
- package/dist/types/jwe/flattened/encrypt.d.ts +1 -1
- package/dist/types/jwe/general/decrypt.d.ts +3 -2
- package/dist/types/jwk/embedded.d.ts +2 -3
- package/dist/types/jwk/from_key_like.d.ts +1 -1
- package/dist/types/jwk/parse.d.ts +1 -1
- package/dist/types/jws/compact/sign.d.ts +1 -1
- package/dist/types/jws/compact/verify.d.ts +3 -2
- package/dist/types/jws/flattened/sign.d.ts +1 -1
- package/dist/types/jws/flattened/verify.d.ts +3 -2
- package/dist/types/jws/general/sign.d.ts +1 -1
- package/dist/types/jws/general/verify.d.ts +3 -2
- package/dist/types/jwt/decrypt.d.ts +3 -2
- package/dist/types/jwt/encrypt.d.ts +2 -2
- package/dist/types/{lib/jwt_producer.d.ts → jwt/produce.d.ts} +1 -1
- package/dist/types/jwt/sign.d.ts +2 -2
- package/dist/types/jwt/unsecured.d.ts +1 -1
- package/dist/types/jwt/verify.d.ts +3 -2
- package/dist/types/key/export.d.ts +5 -0
- package/dist/types/key/import.d.ts +9 -0
- package/dist/types/types.d.ts +101 -5
- package/dist/types/util/errors.d.ts +5 -0
- package/dist/types/util/generate_key_pair.d.ts +2 -2
- package/dist/types/util/generate_secret.d.ts +1 -1
- package/package.json +20 -8
|
@@ -1,30 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const invalid_key_input_js_1 = require("../runtime/invalid_key_input.js");
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const is_key_like_js_1 = require("../runtime/is_key_like.js");
|
|
5
|
+
const symmetricTypeCheck = (key) => {
|
|
6
|
+
if (key instanceof Uint8Array)
|
|
7
|
+
return;
|
|
8
|
+
if (!(0, is_key_like_js_1.default)(key)) {
|
|
9
|
+
throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types, 'Uint8Array'));
|
|
7
10
|
}
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
alg.startsWith('PBES2') ||
|
|
11
|
-
alg.match(/^A\d{3}(?:GCM)?KW$/)) {
|
|
12
|
-
if (key instanceof Uint8Array || key.type === 'secret') {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
throw new TypeError('CryptoKey or KeyObject instances for symmetric algorithms must be of type "secret"');
|
|
11
|
+
if (key.type !== 'secret') {
|
|
12
|
+
throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for symmetric algorithms must be of type "secret"`);
|
|
16
13
|
}
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
};
|
|
15
|
+
const asymmetricTypeCheck = (key, usage) => {
|
|
16
|
+
if (!(0, is_key_like_js_1.default)(key)) {
|
|
17
|
+
throw new TypeError((0, invalid_key_input_js_1.default)(key, ...is_key_like_js_1.types));
|
|
19
18
|
}
|
|
20
19
|
if (key.type === 'secret') {
|
|
21
|
-
throw new TypeError('
|
|
20
|
+
throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`);
|
|
22
21
|
}
|
|
23
22
|
if (usage === 'sign' && key.type === 'public') {
|
|
24
|
-
throw new TypeError('
|
|
23
|
+
throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`);
|
|
25
24
|
}
|
|
26
25
|
if (usage === 'decrypt' && key.type === 'public') {
|
|
27
|
-
throw new TypeError('
|
|
26
|
+
throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
27
|
+
}
|
|
28
|
+
if (key.algorithm && usage === 'verify' && key.type === 'private') {
|
|
29
|
+
throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
30
|
+
}
|
|
31
|
+
if (key.algorithm && usage === 'encrypt' && key.type === 'private') {
|
|
32
|
+
throw new TypeError(`${is_key_like_js_1.types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const checkKeyType = (alg, key, usage) => {
|
|
36
|
+
const symmetric = alg.startsWith('HS') ||
|
|
37
|
+
alg === 'dir' ||
|
|
38
|
+
alg.startsWith('PBES2') ||
|
|
39
|
+
/^A\d{3}(?:GCM)?KW$/.test(alg);
|
|
40
|
+
if (symmetric) {
|
|
41
|
+
symmetricTypeCheck(key);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
asymmetricTypeCheck(key, usage);
|
|
28
45
|
}
|
|
29
46
|
};
|
|
30
47
|
exports.default = checkKeyType;
|
|
@@ -8,83 +8,83 @@ const aesgcmkw_js_1 = require("../runtime/aesgcmkw.js");
|
|
|
8
8
|
const base64url_js_1 = require("../runtime/base64url.js");
|
|
9
9
|
const errors_js_1 = require("../util/errors.js");
|
|
10
10
|
const cek_js_1 = require("../lib/cek.js");
|
|
11
|
-
const
|
|
11
|
+
const import_js_1 = require("../key/import.js");
|
|
12
12
|
const check_key_type_js_1 = require("./check_key_type.js");
|
|
13
|
-
|
|
14
|
-
if (!encryptedKey) {
|
|
15
|
-
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
function assertHeaderParameter(joseHeader, parameter, name) {
|
|
19
|
-
if (joseHeader[parameter] === undefined) {
|
|
20
|
-
throw new errors_js_1.JWEInvalid(`JOSE Header ${name} (${parameter}) missing`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
13
|
+
const is_object_js_1 = require("./is_object.js");
|
|
23
14
|
async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
24
15
|
(0, check_key_type_js_1.default)(alg, key, 'decrypt');
|
|
25
16
|
switch (alg) {
|
|
26
17
|
case 'dir': {
|
|
27
|
-
if (encryptedKey !== undefined)
|
|
18
|
+
if (encryptedKey !== undefined)
|
|
28
19
|
throw new errors_js_1.JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
|
29
|
-
}
|
|
30
20
|
return key;
|
|
31
21
|
}
|
|
32
22
|
case 'ECDH-ES':
|
|
33
|
-
if (encryptedKey !== undefined)
|
|
23
|
+
if (encryptedKey !== undefined)
|
|
34
24
|
throw new errors_js_1.JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
|
35
|
-
}
|
|
36
25
|
case 'ECDH-ES+A128KW':
|
|
37
26
|
case 'ECDH-ES+A192KW':
|
|
38
27
|
case 'ECDH-ES+A256KW': {
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
if (!(0, is_object_js_1.default)(joseHeader.epk))
|
|
29
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
30
|
+
if (!ECDH.ecdhAllowed(key))
|
|
41
31
|
throw new errors_js_1.JOSENotSupported('ECDH-ES with the provided key is not allowed or not supported by your javascript runtime');
|
|
42
|
-
|
|
43
|
-
const epk = await (0, parse_js_1.parseJwk)(joseHeader.epk, alg);
|
|
32
|
+
const epk = await (0, import_js_1.importJWK)(joseHeader.epk, alg);
|
|
44
33
|
let partyUInfo;
|
|
45
34
|
let partyVInfo;
|
|
46
|
-
if (joseHeader.apu !== undefined)
|
|
35
|
+
if (joseHeader.apu !== undefined) {
|
|
36
|
+
if (typeof joseHeader.apu !== 'string')
|
|
37
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
|
|
47
38
|
partyUInfo = (0, base64url_js_1.decode)(joseHeader.apu);
|
|
48
|
-
|
|
39
|
+
}
|
|
40
|
+
if (joseHeader.apv !== undefined) {
|
|
41
|
+
if (typeof joseHeader.apv !== 'string')
|
|
42
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
49
43
|
partyVInfo = (0, base64url_js_1.decode)(joseHeader.apv);
|
|
44
|
+
}
|
|
50
45
|
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, parseInt(alg.substr(-5, 3), 10) || cek_js_1.bitLengths.get(joseHeader.enc), partyUInfo, partyVInfo);
|
|
51
|
-
if (alg === 'ECDH-ES')
|
|
46
|
+
if (alg === 'ECDH-ES')
|
|
52
47
|
return sharedSecret;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return (0, aeskw_js_1.unwrap)(kwAlg, sharedSecret, encryptedKey);
|
|
48
|
+
if (encryptedKey === undefined)
|
|
49
|
+
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
50
|
+
return (0, aeskw_js_1.unwrap)(alg.substr(-6), sharedSecret, encryptedKey);
|
|
57
51
|
}
|
|
58
52
|
case 'RSA1_5':
|
|
59
53
|
case 'RSA-OAEP':
|
|
60
54
|
case 'RSA-OAEP-256':
|
|
61
55
|
case 'RSA-OAEP-384':
|
|
62
56
|
case 'RSA-OAEP-512': {
|
|
63
|
-
|
|
57
|
+
if (encryptedKey === undefined)
|
|
58
|
+
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
64
59
|
return (0, rsaes_js_1.decrypt)(alg, key, encryptedKey);
|
|
65
60
|
}
|
|
66
61
|
case 'PBES2-HS256+A128KW':
|
|
67
62
|
case 'PBES2-HS384+A192KW':
|
|
68
63
|
case 'PBES2-HS512+A256KW': {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
if (encryptedKey === undefined)
|
|
65
|
+
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
66
|
+
if (typeof joseHeader.p2c !== 'number')
|
|
67
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
|
|
68
|
+
if (typeof joseHeader.p2s !== 'string')
|
|
69
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
|
|
70
|
+
return (0, pbes2kw_js_1.decrypt)(alg, key, encryptedKey, joseHeader.p2c, (0, base64url_js_1.decode)(joseHeader.p2s));
|
|
75
71
|
}
|
|
76
72
|
case 'A128KW':
|
|
77
73
|
case 'A192KW':
|
|
78
74
|
case 'A256KW': {
|
|
79
|
-
|
|
75
|
+
if (encryptedKey === undefined)
|
|
76
|
+
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
80
77
|
return (0, aeskw_js_1.unwrap)(alg, key, encryptedKey);
|
|
81
78
|
}
|
|
82
79
|
case 'A128GCMKW':
|
|
83
80
|
case 'A192GCMKW':
|
|
84
81
|
case 'A256GCMKW': {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
if (encryptedKey === undefined)
|
|
83
|
+
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
84
|
+
if (typeof joseHeader.iv !== 'string')
|
|
85
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`);
|
|
86
|
+
if (typeof joseHeader.tag !== 'string')
|
|
87
|
+
throw new errors_js_1.JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
|
|
88
88
|
const iv = (0, base64url_js_1.decode)(joseHeader.iv);
|
|
89
89
|
const tag = (0, base64url_js_1.decode)(joseHeader.tag);
|
|
90
90
|
return (0, aesgcmkw_js_1.unwrap)(alg, key, encryptedKey, iv, tag);
|
|
@@ -9,7 +9,7 @@ const aesgcmkw_js_1 = require("../runtime/aesgcmkw.js");
|
|
|
9
9
|
const base64url_js_1 = require("../runtime/base64url.js");
|
|
10
10
|
const cek_js_1 = require("../lib/cek.js");
|
|
11
11
|
const errors_js_1 = require("../util/errors.js");
|
|
12
|
-
const
|
|
12
|
+
const export_js_1 = require("../key/export.js");
|
|
13
13
|
const check_key_type_js_1 = require("./check_key_type.js");
|
|
14
14
|
const generateCek = (0, cek_js_1.default)(random_js_1.default);
|
|
15
15
|
async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
|
@@ -32,7 +32,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
32
32
|
const { apu, apv } = providedParameters;
|
|
33
33
|
let { epk: ephemeralKey } = providedParameters;
|
|
34
34
|
ephemeralKey || (ephemeralKey = await ECDH.generateEpk(key));
|
|
35
|
-
const { x, y, crv, kty } = await (0,
|
|
35
|
+
const { x, y, crv, kty } = await (0, export_js_1.exportJWK)(ephemeralKey);
|
|
36
36
|
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, parseInt(alg.substr(-5, 3), 10) || cek_js_1.bitLengths.get(enc), apu, apv);
|
|
37
37
|
parameters = { epk: { x, y, crv, kty } };
|
|
38
38
|
if (apu)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = (b64, descriptor) => {
|
|
4
|
+
const newlined = (b64.match(/.{1,64}/g) || []).join('\n');
|
|
5
|
+
return `-----BEGIN ${descriptor}-----\n${newlined}\n-----END ${descriptor}-----`;
|
|
6
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fromSPKI = exports.fromPKCS8 = exports.toPKCS8 = exports.toSPKI = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const webcrypto_js_1 = require("./webcrypto.js");
|
|
6
|
+
const is_key_object_js_1 = require("./is_key_object.js");
|
|
7
|
+
const invalid_key_input_js_1 = require("./invalid_key_input.js");
|
|
8
|
+
const genericExport = (keyType, keyFormat, key) => {
|
|
9
|
+
let keyObject;
|
|
10
|
+
if ((0, webcrypto_js_1.isCryptoKey)(key)) {
|
|
11
|
+
if (!key.extractable) {
|
|
12
|
+
throw new TypeError('CryptoKey is not extractable');
|
|
13
|
+
}
|
|
14
|
+
keyObject = (0, webcrypto_js_1.getKeyObject)(key);
|
|
15
|
+
}
|
|
16
|
+
else if ((0, is_key_object_js_1.default)(key)) {
|
|
17
|
+
keyObject = key;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
throw new TypeError((0, invalid_key_input_js_1.default)(key, 'KeyObject', 'CryptoKey'));
|
|
21
|
+
}
|
|
22
|
+
if (keyObject.type !== keyType) {
|
|
23
|
+
throw new TypeError(`key is not a ${keyType} key`);
|
|
24
|
+
}
|
|
25
|
+
return keyObject.export({ format: 'pem', type: keyFormat });
|
|
26
|
+
};
|
|
27
|
+
const toSPKI = (key) => {
|
|
28
|
+
return genericExport('public', 'spki', key);
|
|
29
|
+
};
|
|
30
|
+
exports.toSPKI = toSPKI;
|
|
31
|
+
const toPKCS8 = (key) => {
|
|
32
|
+
return genericExport('private', 'pkcs8', key);
|
|
33
|
+
};
|
|
34
|
+
exports.toPKCS8 = toPKCS8;
|
|
35
|
+
const fromPKCS8 = (pem) => (0, crypto_1.createPrivateKey)({
|
|
36
|
+
key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, ''), 'base64'),
|
|
37
|
+
type: 'pkcs8',
|
|
38
|
+
format: 'der',
|
|
39
|
+
});
|
|
40
|
+
exports.fromPKCS8 = fromPKCS8;
|
|
41
|
+
const fromSPKI = (pem) => (0, crypto_1.createPublicKey)({
|
|
42
|
+
key: Buffer.from(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, ''), 'base64'),
|
|
43
|
+
type: 'spki',
|
|
44
|
+
format: 'der',
|
|
45
|
+
});
|
|
46
|
+
exports.fromSPKI = fromSPKI;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.decode = exports.encode = void 0;
|
|
3
|
+
exports.decode = exports.encode = exports.encodeBase64 = exports.decodeBase64 = void 0;
|
|
4
4
|
const buffer_utils_js_1 = require("../lib/buffer_utils.js");
|
|
5
5
|
let encodeImpl;
|
|
6
6
|
function normalize(input) {
|
|
@@ -16,6 +16,10 @@ if (Buffer.isEncoding('base64url')) {
|
|
|
16
16
|
else {
|
|
17
17
|
encodeImpl = (input) => Buffer.from(input).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
18
18
|
}
|
|
19
|
+
const decodeBase64 = (input) => Buffer.from(input, 'base64');
|
|
20
|
+
exports.decodeBase64 = decodeBase64;
|
|
21
|
+
const encodeBase64 = (input) => Buffer.from(input).toString('base64');
|
|
22
|
+
exports.encodeBase64 = encodeBase64;
|
|
19
23
|
exports.encode = encodeImpl;
|
|
20
24
|
const decode = (input) => Buffer.from(normalize(input), 'base64');
|
|
21
25
|
exports.decode = decode;
|
|
@@ -18,7 +18,11 @@ const fetchJwks = async (url, timeout, options) => {
|
|
|
18
18
|
agent,
|
|
19
19
|
timeout,
|
|
20
20
|
});
|
|
21
|
-
const [response] = await (0, events_1.once)(req, 'response');
|
|
21
|
+
const [response] = (await Promise.race([(0, events_1.once)(req, 'response'), (0, events_1.once)(req, 'timeout')]));
|
|
22
|
+
if (!response) {
|
|
23
|
+
req.destroy();
|
|
24
|
+
throw new errors_js_1.JWKSTimeout();
|
|
25
|
+
}
|
|
22
26
|
if (response.statusCode !== 200) {
|
|
23
27
|
throw new errors_js_1.JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');
|
|
24
28
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.types = void 0;
|
|
4
|
+
const webcrypto_js_1 = require("./webcrypto.js");
|
|
5
|
+
const is_key_object_js_1 = require("./is_key_object.js");
|
|
6
|
+
exports.default = (key) => (0, is_key_object_js_1.default)(key) || (0, webcrypto_js_1.isCryptoKey)(key);
|
|
7
|
+
const types = ['KeyObject'];
|
|
8
|
+
exports.types = types;
|
|
9
|
+
if (parseInt(process.versions.node) >= 16) {
|
|
10
|
+
types.push('CryptoKey');
|
|
11
|
+
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.JWTExpired = exports.JWSSignatureVerificationFailed = exports.JWKSMultipleMatchingKeys = exports.JWKSNoMatchingKey = exports.JWKSInvalid = exports.JWKInvalid = exports.JWTInvalid = exports.JWSInvalid = exports.JWEInvalid = exports.JWEDecryptionFailed = exports.JOSENotSupported = exports.JOSEAlgNotAllowed = exports.JWTClaimValidationFailed = exports.JOSEError = void 0;
|
|
3
|
+
exports.JWTExpired = exports.JWSSignatureVerificationFailed = exports.JWKSTimeout = exports.JWKSMultipleMatchingKeys = exports.JWKSNoMatchingKey = exports.JWKSInvalid = exports.JWKInvalid = exports.JWTInvalid = exports.JWSInvalid = exports.JWEInvalid = exports.JWEDecryptionFailed = exports.JOSENotSupported = exports.JOSEAlgNotAllowed = exports.JWTClaimValidationFailed = exports.JOSEError = void 0;
|
|
4
4
|
class JOSEError extends Error {
|
|
5
5
|
constructor(message) {
|
|
6
|
+
var _a;
|
|
6
7
|
super(message);
|
|
7
8
|
this.code = JOSEError.code;
|
|
8
9
|
this.name = this.constructor.name;
|
|
9
|
-
|
|
10
|
-
Error.captureStackTrace(this, this.constructor);
|
|
11
|
-
}
|
|
10
|
+
(_a = Error.captureStackTrace) === null || _a === void 0 ? void 0 : _a.call(Error, this, this.constructor);
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
13
|
exports.JOSEError = JOSEError;
|
|
@@ -106,6 +105,15 @@ class JWKSMultipleMatchingKeys extends JOSEError {
|
|
|
106
105
|
}
|
|
107
106
|
exports.JWKSMultipleMatchingKeys = JWKSMultipleMatchingKeys;
|
|
108
107
|
JWKSMultipleMatchingKeys.code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';
|
|
108
|
+
class JWKSTimeout extends JOSEError {
|
|
109
|
+
constructor() {
|
|
110
|
+
super(...arguments);
|
|
111
|
+
this.code = JWKSTimeout.code;
|
|
112
|
+
this.message = 'request timed out';
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.JWKSTimeout = JWKSTimeout;
|
|
116
|
+
JWKSTimeout.code = 'ERR_JWKS_TIMEOUT';
|
|
109
117
|
class JWSSignatureVerificationFailed extends JOSEError {
|
|
110
118
|
constructor() {
|
|
111
119
|
super(...arguments);
|
|
@@ -19,7 +19,11 @@ async function compactDecrypt(jwe, key, options) {
|
|
|
19
19
|
tag: (tag || undefined),
|
|
20
20
|
encrypted_key: encryptedKey || undefined,
|
|
21
21
|
}, key, options);
|
|
22
|
-
|
|
22
|
+
const result = { plaintext: decrypted.plaintext, protectedHeader: decrypted.protectedHeader };
|
|
23
|
+
if (typeof key === 'function') {
|
|
24
|
+
return { ...result, key: decrypted.key };
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
23
27
|
}
|
|
24
28
|
export { compactDecrypt };
|
|
25
29
|
export default compactDecrypt;
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import
|
|
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,8 +9,8 @@ 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
|
|
13
|
-
if (key.type !== 'public') {
|
|
12
|
+
const key = await importJWK({ ...joseHeader.jwk, ext: true }, joseHeader.alg, true);
|
|
13
|
+
if (key instanceof Uint8Array || key.type !== 'public') {
|
|
14
14
|
throw new JWSInvalid('"jwk" (JSON Web Key) Header Parameter must be a public key');
|
|
15
15
|
}
|
|
16
16
|
return key;
|
|
@@ -1,35 +1,6 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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,9 +1,9 @@
|
|
|
1
1
|
import fetchJwks from '../runtime/fetch_jwks.js';
|
|
2
|
-
import
|
|
2
|
+
import { importJWK } from '../key/import.js';
|
|
3
3
|
import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';
|
|
4
4
|
import isObject from '../lib/is_object.js';
|
|
5
5
|
function getKtyFromAlg(alg) {
|
|
6
|
-
switch (alg.substr(0, 2)) {
|
|
6
|
+
switch (typeof alg === 'string' && alg.substr(0, 2)) {
|
|
7
7
|
case 'RS':
|
|
8
8
|
case 'PS':
|
|
9
9
|
return 'RSA';
|
|
@@ -32,7 +32,7 @@ class RemoteJWKSet {
|
|
|
32
32
|
typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000;
|
|
33
33
|
}
|
|
34
34
|
coolingDown() {
|
|
35
|
-
if (
|
|
35
|
+
if (!this._cooldownStarted) {
|
|
36
36
|
return false;
|
|
37
37
|
}
|
|
38
38
|
return Date.now() < this._cooldownStarted + this._cooldownDuration;
|
|
@@ -56,7 +56,7 @@ class RemoteJWKSet {
|
|
|
56
56
|
candidate = jwk.key_ops.includes('verify');
|
|
57
57
|
}
|
|
58
58
|
if (candidate && protectedHeader.alg === 'EdDSA') {
|
|
59
|
-
candidate =
|
|
59
|
+
candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';
|
|
60
60
|
}
|
|
61
61
|
if (candidate) {
|
|
62
62
|
switch (protectedHeader.alg) {
|
|
@@ -88,13 +88,10 @@ class RemoteJWKSet {
|
|
|
88
88
|
else if (length !== 1) {
|
|
89
89
|
throw new JWKSMultipleMatchingKeys();
|
|
90
90
|
}
|
|
91
|
-
|
|
92
|
-
this._cached.set(jwk, {});
|
|
93
|
-
}
|
|
94
|
-
const cached = this._cached.get(jwk);
|
|
91
|
+
const cached = this._cached.get(jwk) || this._cached.set(jwk, {}).get(jwk);
|
|
95
92
|
if (cached[protectedHeader.alg] === undefined) {
|
|
96
|
-
const keyObject = await
|
|
97
|
-
if (keyObject.type !== 'public') {
|
|
93
|
+
const keyObject = await importJWK({ ...jwk, ext: true }, protectedHeader.alg);
|
|
94
|
+
if (keyObject instanceof Uint8Array || keyObject.type !== 'public') {
|
|
98
95
|
throw new JWKSInvalid('JSON Web Key Set members must be public keys');
|
|
99
96
|
}
|
|
100
97
|
cached[protectedHeader.alg] = keyObject;
|
|
@@ -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
|
-
|
|
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;
|
|
@@ -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
|
-
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import CompactEncrypt from '../jwe/compact/encrypt.js';
|
|
2
2
|
import { encoder } from '../lib/buffer_utils.js';
|
|
3
|
-
import ProduceJWT from '
|
|
3
|
+
import { ProduceJWT } from './produce.js';
|
|
4
4
|
class EncryptJWT extends ProduceJWT {
|
|
5
5
|
setProtectedHeader(protectedHeader) {
|
|
6
6
|
if (this._protectedHeader) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import epoch from '
|
|
2
|
-
import isObject from '
|
|
3
|
-
import secs from '
|
|
4
|
-
export
|
|
1
|
+
import epoch from '../lib/epoch.js';
|
|
2
|
+
import isObject from '../lib/is_object.js';
|
|
3
|
+
import secs from '../lib/secs.js';
|
|
4
|
+
export class ProduceJWT {
|
|
5
5
|
constructor(payload) {
|
|
6
6
|
if (!isObject(payload)) {
|
|
7
7
|
throw new TypeError('JWT Claims Set MUST be an object');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import CompactSign from '../jws/compact/sign.js';
|
|
2
2
|
import { JWTInvalid } from '../util/errors.js';
|
|
3
3
|
import { encoder } from '../lib/buffer_utils.js';
|
|
4
|
-
import ProduceJWT from '
|
|
4
|
+
import { ProduceJWT } from './produce.js';
|
|
5
5
|
class SignJWT extends ProduceJWT {
|
|
6
6
|
setProtectedHeader(protectedHeader) {
|
|
7
7
|
this._protectedHeader = protectedHeader;
|
|
@@ -2,7 +2,7 @@ import * as base64url from '../runtime/base64url.js';
|
|
|
2
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
|
-
import ProduceJWT from '
|
|
5
|
+
import { ProduceJWT } from './produce.js';
|
|
6
6
|
class UnsecuredJWT extends ProduceJWT {
|
|
7
7
|
encode() {
|
|
8
8
|
const header = base64url.encode(JSON.stringify({ alg: 'none' }));
|
|
@@ -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
|
-
|
|
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
|
+
}
|