From 1c0dbeb6ddbdbea7751668ddf16be2b938d9a11b Mon Sep 17 00:00:00 2001 From: Stoian Ivanov Date: Mon, 29 Mar 2021 16:54:19 +0300 Subject: [PATCH 1/2] ES384 support --- src/JWT.php | 8 ++++++-- tests/JWTTest.php | 16 ++++++++++++++++ tests/ecdsa384-private.pem | 6 ++++++ tests/ecdsa384-public.pem | 5 +++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/ecdsa384-private.pem create mode 100644 tests/ecdsa384-public.pem diff --git a/src/JWT.php b/src/JWT.php index b167abd7..0ac46164 100644 --- a/src/JWT.php +++ b/src/JWT.php @@ -42,6 +42,7 @@ class JWT public static $timestamp = null; public static $supported_algs = array( + 'ES384' => array('openssl', 'SHA384'), 'ES256' => array('openssl', 'SHA256'), 'HS256' => array('hash_hmac', 'SHA256'), 'HS384' => array('hash_hmac', 'SHA384'), @@ -102,8 +103,8 @@ public static function decode($jwt, $key, array $allowed_algs = array()) if (!\in_array($header->alg, $allowed_algs)) { throw new UnexpectedValueException('Algorithm not allowed'); } - if ($header->alg === 'ES256') { - // OpenSSL expects an ASN.1 DER sequence for ES256 signatures + if ($header->alg === 'ES256' || $header->alg === 'ES384') { + // OpenSSL expects an ASN.1 DER sequence for ES256/ES384 signatures $sig = self::signatureToDER($sig); } @@ -214,6 +215,9 @@ public static function sign($msg, $key, $alg = 'HS256') if ($alg === 'ES256') { $signature = self::signatureFromDER($signature, 256); } + if ($alg === 'ES384') { + $signature = self::signatureFromDER($signature, 384); + } return $signature; } } diff --git a/tests/JWTTest.php b/tests/JWTTest.php index fc9c3756..3dc28bf2 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -299,4 +299,20 @@ public function testEncodeAndDecodeEcdsaToken() $this->assertEquals('bar', $decoded->foo); } + + /** + * @runInSeparateProcess + */ + public function testEncodeAndDecodeEcdsa384Token() + { + $privateKey = file_get_contents(__DIR__ . '/ecdsa384-private.pem'); + $payload = array('foo' => 'bar'); + $encoded = JWT::encode($payload, $privateKey, 'ES384'); + + // Verify decoding succeeds + $publicKey = file_get_contents(__DIR__ . '/ecdsa384-public.pem'); + $decoded = JWT::decode($encoded, $publicKey, array('ES384')); + + $this->assertEquals('bar', $decoded->foo); + } } diff --git a/tests/ecdsa384-private.pem b/tests/ecdsa384-private.pem new file mode 100644 index 00000000..ee593e6f --- /dev/null +++ b/tests/ecdsa384-private.pem @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBQJuwafREZ1494Fm2MTVXuZbWXVAOwIAxGhyLdc3CChzi0FVXZq8e6 +65oR0Qq9Jv2gBwYFK4EEACKhZANiAAQWFddzIqZaROR1VtZhhTd20mqknQmYsZ+0 +R03NQQUQpJTkyWcuv8WNyd6zO9cCoQEzi94kX907/OEWTjhuH8QtdunT+ef1BpWJ +W1Cm5O+m7b155/Ho99QypfQr74hLg1A= +-----END EC PRIVATE KEY----- diff --git a/tests/ecdsa384-public.pem b/tests/ecdsa384-public.pem new file mode 100644 index 00000000..475f1348 --- /dev/null +++ b/tests/ecdsa384-public.pem @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEFhXXcyKmWkTkdVbWYYU3dtJqpJ0JmLGf +tEdNzUEFEKSU5MlnLr/FjcneszvXAqEBM4veJF/dO/zhFk44bh/ELXbp0/nn9QaV +iVtQpuTvpu29eefx6PfUMqX0K++IS4NQ +-----END PUBLIC KEY----- From 6749a4a2193febdee24e9b67bf0be663d4cdeb23 Mon Sep 17 00:00:00 2001 From: Stoian Ivanov Date: Mon, 29 Mar 2021 19:55:10 +0300 Subject: [PATCH 2/2] Update php doc comments with the newly supported algorithm --- src/JWT.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/JWT.php b/src/JWT.php index 0ac46164..c68d4e15 100644 --- a/src/JWT.php +++ b/src/JWT.php @@ -59,7 +59,8 @@ class JWT * @param string|array|resource $key The key, or map of keys. * If the algorithm used is asymmetric, this is the public key * @param array $allowed_algs List of supported verification algorithms - * Supported algorithms are 'ES256', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' + * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', + * 'HS512', 'RS256', 'RS384', and 'RS512' * * @return object The JWT's payload as a PHP object * @@ -156,7 +157,8 @@ public static function decode($jwt, $key, array $allowed_algs = array()) * @param string $key The secret key. * If the algorithm used is asymmetric, this is the private key * @param string $alg The signing algorithm. - * Supported algorithms are 'ES256', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' + * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', + * 'HS512', 'RS256', 'RS384', and 'RS512' * @param mixed $keyId * @param array $head An array with header elements to attach * @@ -191,7 +193,8 @@ public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $he * @param string $msg The message to sign * @param string|resource $key The secret key * @param string $alg The signing algorithm. - * Supported algorithms are 'ES256', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' + * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', + * 'HS512', 'RS256', 'RS384', and 'RS512' * * @return string An encrypted message *