diff --git a/src/JWT.php b/src/JWT.php index b167abd7..c68d4e15 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'), @@ -58,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 * @@ -102,8 +104,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); } @@ -155,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 * @@ -190,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 * @@ -214,6 +218,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 bc9d7a8c..2516ec0d 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -300,4 +300,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-----