Skip to content

Commit aa90549

Browse files
committed
feat: add support for Ed25519 and Ed448 (EdDSA)
1 parent 249d10a commit aa90549

11 files changed

+44
-3
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,11 @@ As mentioned in [this comment](https://github.com/auth0/node-jsonwebtoken/issues
144144
* `algorithms`: List of strings with the names of the allowed algorithms. For instance, `["HS256", "HS384"]`.
145145
> If not specified a defaults will be used based on the type of key provided
146146
> * secret - ['HS256', 'HS384', 'HS512']
147-
> * rsa - ['RS256', 'RS384', 'RS512']
148-
> * ec - ['ES256', 'ES384', 'ES512']
149-
> * default - ['RS256', 'RS384', 'RS512']
147+
> * rsa - ['RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512']
148+
> * rsa-pss - ['PS256', 'PS384', 'PS512']
149+
> * ec - ['ES256', 'ES256K', 'ES384', 'ES512']
150+
> * ed25519 - ['EdDSA', 'Ed25519']
151+
> * ed448 - ['EdDSA', 'Ed448']
150152
* `audience`: if you want to check audience (`aud`), provide a value here. The audience can be checked against a string, a regular expression or a list of strings and/or regular expressions.
151153
> Eg: `"urn:foo"`, `/urn:f[o]{2}/`, `[/urn:f[o]{2}/, "urn:bar"]`
152154
* `complete`: return an object with the decoded `{ payload, header, signature }` instead of only the usual content of the payload.
@@ -370,6 +372,9 @@ Array of supported algorithms. The following algorithms are currently supported.
370372
| ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm |
371373
| ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm |
372374
| ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm |
375+
| EdDSA (deprecated) | EdDSA using Ed25519 or Ed448 |
376+
| Ed25519 | EdDSA using Ed25519 |
377+
| Ed448 | EdDSA using Ed448 |
373378
| none | No digital signature or MAC value included |
374379

375380
## Refreshing JWTs

lib/oneShotAlgs.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ module.exports = function(alg, key) {
5252
digest: 'sha512',
5353
key: { key, dsaEncoding: 'ieee-p1363' },
5454
};
55+
case 'Ed25519':
56+
case 'Ed448':
57+
case 'EdDSA':
58+
return {
59+
digest: undefined,
60+
key: { key },
61+
};
5562
default:
5663
throw new Error('unreachable');
5764
}

lib/validateAsymmetricKey.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ const { ASYMMETRIC_KEY_DETAILS_SUPPORTED, RSA_PSS_KEY_DETAILS_SUPPORTED } = requ
22

33
const allowedAlgorithmsForKeys = {
44
'ec': ['ES256', 'ES256K', 'ES384', 'ES512'],
5+
'ed25519': ['EdDSA'],
6+
'ed448': ['EdDSA'],
57
'rsa': ['RS256', 'PS256', 'RS384', 'PS384', 'RS512', 'PS512'],
68
'rsa-pss': ['PS256', 'PS384', 'PS512']
79
};

sign.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const SUPPORTED_ALGS = [
1515
'PS256', 'PS384', 'PS512',
1616
'ES256', 'ES256K', 'ES384', 'ES512',
1717
'HS256', 'HS384', 'HS512',
18+
'EdDSA',
19+
'Ed25519', 'Ed448',
1820
'none',
1921
];
2022

test/ed25519-private.pem

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MC4CAQAwBQYDK2VwBCIEINm0OEjPHWFVPXX+RWO48diNrzeWvhxLYT0UfBHb6ZBA
3+
-----END PRIVATE KEY-----

test/ed25519-public-invalid.pem

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MCowBQYDK2VwAyEAnbt7ZRTDvGWNmgiJQ+oOodLqvFS0fl1mlRHTaetHI0Q=
3+
-----END PUBLIC KEY-----

test/ed25519-public.pem

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MCowBQYDK2VwAyEAbelG8IgnkVHYUdI5CN54QDdYkvgJkeDc7V8EVBN6zVg=
3+
-----END PUBLIC KEY-----

test/jwt.asymmetric_signing.tests.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const algorithms = {
2626
pub_key: loadKey('secp256k1-public.pem'),
2727
invalid_pub_key: loadKey('secp256k1-public-invalid.pem')
2828
},
29+
EdDSA: {
30+
priv_key: loadKey('ed25519-private.pem'),
31+
pub_key: loadKey('ed25519-public.pem'),
32+
invalid_pub_key: loadKey('ed25519-public-invalid.pem')
33+
},
2934
PS256: {
3035
pub_key: loadKey('pub.pem'),
3136
priv_key: loadKey('priv.pem'),

test/roundtrip.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ for (const [alg, opts] of [
1414
["ES256K"],
1515
["ES384"],
1616
["ES512"],
17+
["EdDSA", { crv: "Ed25519" }],
18+
["EdDSA", { crv: "Ed448" }],
1719
]) {
1820
const conditionalDescribe =
1921
parseInt(process.versions.node, 10) >= 18 ? describe : describe.skip;

test/schema.tests.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ describe('schema', function() {
1010
var cert_secp256k1_priv = fs.readFileSync(__dirname + '/secp256k1-private.pem');
1111
var cert_secp384r1_priv = fs.readFileSync(__dirname + '/secp384r1-private.pem');
1212
var cert_secp521r1_priv = fs.readFileSync(__dirname + '/secp521r1-private.pem');
13+
var cert_ed25519_priv = fs.readFileSync(__dirname + '/ed25519-private.pem');
1314

1415
function sign(options, secretOrPrivateKey) {
1516
jwt.sign({foo: 123}, secretOrPrivateKey, options);
@@ -30,6 +31,7 @@ describe('schema', function() {
3031
sign({algorithm: 'ES256K'}, cert_secp256k1_priv);
3132
sign({algorithm: 'ES384'}, cert_secp384r1_priv);
3233
sign({algorithm: 'ES512'}, cert_secp521r1_priv);
34+
sign({algorithm: 'EdDSA'}, cert_ed25519_priv);
3335
sign({algorithm: 'HS256'}, 'superSecret');
3436
sign({algorithm: 'HS384'}, 'superSecret');
3537
sign({algorithm: 'HS512'}, 'superSecret');

verify.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const RSA_KEY_ALGS = ['RS256', 'RS384', 'RS512'];
1212
const RSA_PSS_KEY_ALGS = ['PS256', 'PS384', 'PS512'];
1313
const PUB_KEY_ALGS = [].concat(RSA_KEY_ALGS, EC_KEY_ALGS);
1414
const HS_ALGS = ['HS256', 'HS384', 'HS512'];
15+
const EdDSA_ALGS = ['EdDSA'];
1516

1617
function processPayload(header, payload, signature, options, done) {
1718
const clockTimestamp = options.clockTimestamp || Math.floor(Date.now() / 1000);
@@ -225,6 +226,12 @@ module.exports = function(jwtString, secretOrPublicKey, options, callback) {
225226
case 'ec':
226227
options.algorithms = EC_KEY_ALGS;
227228
break;
229+
case 'ed25519':
230+
options.algorithms = [].concat(EdDSA_ALGS, 'Ed25519');
231+
break;
232+
case 'ed448':
233+
options.algorithms = [].concat(EdDSA_ALGS, 'Ed448');
234+
break;
228235
default:
229236
options.algorithms = PUB_KEY_ALGS;
230237
}

0 commit comments

Comments
 (0)