Skip to content

Commit c0d9ca0

Browse files
committed
refactor: use async node:crypto methods when available
1 parent 2c0e670 commit c0d9ca0

20 files changed

+530
-241
lines changed

.circleci/config.yml

+29-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: 2.1
33
# Thanks to https://github.com/teppeis-sandbox/circleci2-multiple-node-versions
44

55
commands:
6-
test-nodejs:
6+
test-modern:
77
steps:
88
- run:
99
name: Versions
@@ -15,28 +15,50 @@ commands:
1515
- run:
1616
name: Test
1717
command: npm test
18+
test-legacy:
19+
steps:
20+
- run:
21+
name: Versions
22+
command: npm version
23+
- checkout
24+
- run:
25+
name: Install dependencies
26+
command: npm install
27+
- run:
28+
name: Test
29+
command: npm run test-only
1830

1931
jobs:
2032
node-v12:
2133
docker:
2234
- image: node:12
2335
steps:
24-
- test-nodejs
36+
- test-legacy
2537
node-v14:
2638
docker:
2739
- image: node:14
2840
steps:
29-
- test-nodejs
41+
- test-legacy
3042
node-v16:
3143
docker:
3244
- image: node:16
3345
steps:
34-
- test-nodejs
46+
- test-modern
3547
node-v18:
3648
docker:
3749
- image: node:18
3850
steps:
39-
- test-nodejs
51+
- test-modern
52+
node-v20:
53+
docker:
54+
- image: node:20
55+
steps:
56+
- test-modern
57+
node-v22:
58+
docker:
59+
- image: node:22
60+
steps:
61+
- test-modern
4062

4163
workflows:
4264
node-multi-build:
@@ -45,3 +67,5 @@ workflows:
4567
- node-v14
4668
- node-v16
4769
- node-v18
70+
- node-v20
71+
- node-v22

decode.js

+46-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,52 @@
1-
var jws = require('jws');
1+
function payloadFromJWS(encodedPayload, encoding = "utf8") {
2+
try {
3+
return Buffer.from(encodedPayload, "base64").toString(encoding);
4+
} catch (_) {
5+
return;
6+
}
7+
}
8+
9+
function headerFromJWS(encodedHeader) {
10+
try {
11+
return JSON.parse(Buffer.from(encodedHeader, "base64").toString());
12+
} catch (_) {
13+
return;
14+
}
15+
}
16+
17+
const JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
18+
19+
function isValidJws(string) {
20+
return JWS_REGEX.test(string);
21+
}
22+
23+
function jwsDecode(token, opts) {
24+
opts = opts || {};
25+
26+
if (!isValidJws(token)) return null;
27+
28+
let [header, payload, signature] = token.split('.');
29+
30+
header = headerFromJWS(header);
31+
if (header === undefined) return null;
32+
33+
payload = payloadFromJWS(payload);
34+
if (payload === undefined) return null;
35+
36+
if (header.typ === "JWT" || opts.json){
37+
payload = JSON.parse(payload);
38+
}
39+
40+
return {
41+
header,
42+
payload,
43+
signature,
44+
};
45+
}
246

347
module.exports = function (jwt, options) {
448
options = options || {};
5-
var decoded = jws.decode(jwt, options);
49+
const decoded = jwsDecode(jwt, options);
650
if (!decoded) { return null; }
751
var payload = decoded.payload;
852

lib/asymmetricKeyDetailsSupported.js

-3
This file was deleted.

lib/base64url.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* istanbul ignore file */
2+
if (Buffer.isEncoding("base64url")) {
3+
module.exports = (buf) => buf.toString("base64url");
4+
} else {
5+
const fromBase64 = (base64) =>
6+
// eslint-disable-next-line no-div-regex
7+
base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
8+
module.exports = (buf) => fromBase64(buf.toString("base64"));
9+
}

lib/flags.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* istanbul ignore file */
2+
const [major, minor] = process.versions.node.split('.').map((v) => parseInt(v, 10));
3+
4+
module.exports.RSA_PSS_KEY_DETAILS_SUPPORTED = major > 16 || (major === 16 && minor >= 9);
5+
module.exports.ASYMMETRIC_KEY_DETAILS_SUPPORTED = major > 15 || (major === 15 && minor >= 7);

lib/oneShotAlgs.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const { constants } = require("crypto");
2+
3+
module.exports = function(alg, key) {
4+
switch (alg) {
5+
case 'RS256':
6+
return {
7+
digest: 'sha256',
8+
key: { key, padding: constants.RSA_PKCS1_PADDING },
9+
};
10+
case 'RS384':
11+
return {
12+
digest: 'sha384',
13+
key: { key, padding: constants.RSA_PKCS1_PADDING },
14+
};
15+
case 'RS512':
16+
return {
17+
digest: 'sha512',
18+
key: { key, padding: constants.RSA_PKCS1_PADDING },
19+
};
20+
case 'PS256':
21+
return {
22+
digest: 'sha256',
23+
key: { key, padding: constants.RSA_PKCS1_PSS_PADDING, saltLength: constants.RSA_PSS_SALTLEN_DIGEST },
24+
};
25+
case 'PS384':
26+
return {
27+
digest: 'sha384',
28+
key: { key, padding: constants.RSA_PKCS1_PSS_PADDING, saltLength: constants.RSA_PSS_SALTLEN_DIGEST },
29+
};
30+
case 'PS512':
31+
return {
32+
digest: 'sha512',
33+
key: { key, padding: constants.RSA_PKCS1_PSS_PADDING, saltLength: constants.RSA_PSS_SALTLEN_DIGEST },
34+
};
35+
case 'ES256':
36+
return {
37+
digest: 'sha256',
38+
key: { key, dsaEncoding: 'ieee-p1363' },
39+
};
40+
case 'ES384':
41+
return {
42+
digest: 'sha384',
43+
key: { key, dsaEncoding: 'ieee-p1363' },
44+
};
45+
case 'ES512':
46+
return {
47+
digest: 'sha512',
48+
key: { key, dsaEncoding: 'ieee-p1363' },
49+
};
50+
default:
51+
throw new Error('unreachable');
52+
}
53+
};

lib/psSupported.js

-3
This file was deleted.

lib/rsaPssKeyDetailsSupported.js

-3
This file was deleted.

lib/validateAsymmetricKey.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
const ASYMMETRIC_KEY_DETAILS_SUPPORTED = require('./asymmetricKeyDetailsSupported');
2-
const RSA_PSS_KEY_DETAILS_SUPPORTED = require('./rsaPssKeyDetailsSupported');
1+
const { ASYMMETRIC_KEY_DETAILS_SUPPORTED, RSA_PSS_KEY_DETAILS_SUPPORTED } = require('./flags');
32

43
const allowedAlgorithmsForKeys = {
54
'ec': ['ES256', 'ES384', 'ES512'],
@@ -52,7 +51,7 @@ module.exports = function(algorithm, key) {
5251
const length = parseInt(algorithm.slice(-3), 10);
5352
const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails;
5453

55-
if (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm) {
54+
if (hashAlgorithm !== undefined && (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) {
5655
throw new Error(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${algorithm}.`);
5756
}
5857

package.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"scripts": {
2222
"lint": "eslint .",
2323
"coverage": "nyc mocha --use_strict",
24-
"test": "npm run lint && npm run coverage && cost-of-modules"
24+
"test": "npm run lint && npm run coverage && cost-of-modules",
25+
"test-only": "mocha --use_strict"
2526
},
2627
"repository": {
2728
"type": "git",
@@ -36,23 +37,23 @@
3637
"url": "https://github.com/auth0/node-jsonwebtoken/issues"
3738
},
3839
"dependencies": {
39-
"jws": "^3.2.2",
4040
"lodash.includes": "^4.3.0",
4141
"lodash.isboolean": "^3.0.3",
4242
"lodash.isinteger": "^4.0.4",
4343
"lodash.isnumber": "^3.0.3",
4444
"lodash.isplainobject": "^4.0.6",
4545
"lodash.isstring": "^4.0.1",
4646
"lodash.once": "^4.0.0",
47-
"ms": "^2.1.1",
48-
"semver": "^7.5.4"
47+
"ms": "^2.1.1"
4948
},
5049
"devDependencies": {
5150
"atob": "^2.1.2",
5251
"chai": "^4.1.2",
5352
"conventional-changelog": "~1.1.0",
5453
"cost-of-modules": "^1.0.1",
5554
"eslint": "^4.19.1",
55+
"jose": "^5.8.0",
56+
"jws": "^3.2.2",
5657
"mocha": "^5.2.0",
5758
"nsp": "^2.6.2",
5859
"nyc": "^11.9.0",

0 commit comments

Comments
 (0)