From 1ac4354598c2ef1b0692094ac9a31dae137914fd Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 11 Sep 2024 13:35:01 +0200 Subject: [PATCH] feat: add support for curve secp256k1 (ES256K) --- lib/oneShotAlgs.js | 5 +++++ lib/validateAsymmetricKey.js | 3 ++- sign.js | 2 +- test/jwt.asymmetric_signing.tests.js | 5 +++++ test/roundtrip.test.js | 1 + test/schema.tests.js | 2 ++ test/secp256k1-private.pem | 5 +++++ test/secp256k1-public-invalid.pem | 4 ++++ test/secp256k1-public.pem | 4 ++++ verify.js | 2 +- 10 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test/secp256k1-private.pem create mode 100644 test/secp256k1-public-invalid.pem create mode 100644 test/secp256k1-public.pem diff --git a/lib/oneShotAlgs.js b/lib/oneShotAlgs.js index 2be1359..8e3550c 100644 --- a/lib/oneShotAlgs.js +++ b/lib/oneShotAlgs.js @@ -37,6 +37,11 @@ module.exports = function(alg, key) { digest: 'sha256', key: { key, dsaEncoding: 'ieee-p1363' }, }; + case 'ES256K': + return { + digest: 'sha256', + key: { key, dsaEncoding: 'ieee-p1363' }, + }; case 'ES384': return { digest: 'sha384', diff --git a/lib/validateAsymmetricKey.js b/lib/validateAsymmetricKey.js index 447bd91..77d5bf3 100644 --- a/lib/validateAsymmetricKey.js +++ b/lib/validateAsymmetricKey.js @@ -1,13 +1,14 @@ const { ASYMMETRIC_KEY_DETAILS_SUPPORTED, RSA_PSS_KEY_DETAILS_SUPPORTED } = require('./flags'); const allowedAlgorithmsForKeys = { - 'ec': ['ES256', 'ES384', 'ES512'], + 'ec': ['ES256', 'ES256K', 'ES384', 'ES512'], 'rsa': ['RS256', 'PS256', 'RS384', 'PS384', 'RS512', 'PS512'], 'rsa-pss': ['PS256', 'PS384', 'PS512'] }; const allowedCurves = { ES256: 'prime256v1', + ES256K: 'secp256k1', ES384: 'secp384r1', ES512: 'secp521r1', }; diff --git a/sign.js b/sign.js index 77c070e..6f60b16 100644 --- a/sign.js +++ b/sign.js @@ -13,7 +13,7 @@ const encodeBase64url = require('./lib/base64url'); const SUPPORTED_ALGS = [ 'RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512', - 'ES256', 'ES384', 'ES512', + 'ES256', 'ES256K', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none', ]; diff --git a/test/jwt.asymmetric_signing.tests.js b/test/jwt.asymmetric_signing.tests.js index dfd1d38..a0f8415 100644 --- a/test/jwt.asymmetric_signing.tests.js +++ b/test/jwt.asymmetric_signing.tests.js @@ -21,6 +21,11 @@ const algorithms = { pub_key: loadKey('ecdsa-public.pem'), invalid_pub_key: loadKey('ecdsa-public-invalid.pem') }, + ES256K: { + priv_key: loadKey('secp256k1-private.pem'), + pub_key: loadKey('secp256k1-public.pem'), + invalid_pub_key: loadKey('secp256k1-public-invalid.pem') + }, PS256: { pub_key: loadKey('pub.pem'), priv_key: loadKey('priv.pem'), diff --git a/test/roundtrip.test.js b/test/roundtrip.test.js index 0995c5f..2b3c263 100644 --- a/test/roundtrip.test.js +++ b/test/roundtrip.test.js @@ -11,6 +11,7 @@ for (const [alg, opts] of [ ["RS256"], ["PS256"], ["ES256"], + ["ES256K"], ["ES384"], ["ES512"], ]) { diff --git a/test/schema.tests.js b/test/schema.tests.js index 0033ab4..6def721 100644 --- a/test/schema.tests.js +++ b/test/schema.tests.js @@ -7,6 +7,7 @@ describe('schema', function() { describe('sign options', function() { var cert_rsa_priv = fs.readFileSync(__dirname + '/rsa-private.pem'); var cert_ecdsa_priv = fs.readFileSync(__dirname + '/ecdsa-private.pem'); + var cert_secp256k1_priv = fs.readFileSync(__dirname + '/secp256k1-private.pem'); var cert_secp384r1_priv = fs.readFileSync(__dirname + '/secp384r1-private.pem'); var cert_secp521r1_priv = fs.readFileSync(__dirname + '/secp521r1-private.pem'); @@ -26,6 +27,7 @@ describe('schema', function() { sign({algorithm: 'PS384'}, cert_rsa_priv); sign({algorithm: 'PS512'}, cert_rsa_priv); sign({algorithm: 'ES256'}, cert_ecdsa_priv); + sign({algorithm: 'ES256K'}, cert_secp256k1_priv); sign({algorithm: 'ES384'}, cert_secp384r1_priv); sign({algorithm: 'ES512'}, cert_secp521r1_priv); sign({algorithm: 'HS256'}, 'superSecret'); diff --git a/test/secp256k1-private.pem b/test/secp256k1-private.pem new file mode 100644 index 0000000..1d05b81 --- /dev/null +++ b/test/secp256k1-private.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIFg3x9PMwysC/B5iW1zUFqDUfNbgP77i71jEPhoce0OkoAcGBSuBBAAK +oUQDQgAEUdPp6J0l51augh0A0sB14n2j69er1ZTkhfv+XY3CIU/SFK/BmIt0KfAX +VF2KGowflLSKkySNnfR93uwnf7y1MQ== +-----END EC PRIVATE KEY----- diff --git a/test/secp256k1-public-invalid.pem b/test/secp256k1-public-invalid.pem new file mode 100644 index 0000000..5a84eed --- /dev/null +++ b/test/secp256k1-public-invalid.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE7cjAbx1KnvP+g5lJQba/42ga/NL5rkIC +rmuRulSLZ+X6oRvnxfhgDkQgkoJkNaqXR6vYE42kfbz5BOfIcNfkig== +-----END PUBLIC KEY----- diff --git a/test/secp256k1-public.pem b/test/secp256k1-public.pem new file mode 100644 index 0000000..aaa8fc9 --- /dev/null +++ b/test/secp256k1-public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEUdPp6J0l51augh0A0sB14n2j69er1ZTk +hfv+XY3CIU/SFK/BmIt0KfAXVF2KGowflLSKkySNnfR93uwnf7y1MQ== +-----END PUBLIC KEY----- diff --git a/verify.js b/verify.js index fcd1739..de3f3e8 100644 --- a/verify.js +++ b/verify.js @@ -7,7 +7,7 @@ const validateAsymmetricKey = require('./lib/validateAsymmetricKey'); const crypto = require("crypto"); const oneShotAlgs = require('./lib/oneShotAlgs'); -const EC_KEY_ALGS = ['ES256', 'ES384', 'ES512']; +const EC_KEY_ALGS = ['ES256', 'ES256K', 'ES384', 'ES512']; const RSA_KEY_ALGS = ['RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512']; const PUB_KEY_ALGS = [].concat(RSA_KEY_ALGS, EC_KEY_ALGS); const HS_ALGS = ['HS256', 'HS384', 'HS512'];