Skip to content

Commit

Permalink
Fix compatibility with PHP 8.0
Browse files Browse the repository at this point in the history
As of PHP 8.0, OpenSSL keys are ojects (OpenSSLAsymmetricKey) instead of
resources.
  • Loading branch information
lcobucci committed Sep 29, 2020
1 parent a9c4bb2 commit be0f2f9
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 16 deletions.
4 changes: 2 additions & 2 deletions infection.json.dist
Expand Up @@ -10,7 +10,7 @@
"@default": true,
"@function_signature": true
},
"minMsi": 94.22,
"minCoveredMsi": 94.22,
"minMsi": 92.54,
"minCoveredMsi": 92.54,
"testFrameworkOptions": "--testsuite=unit"
}
3 changes: 3 additions & 0 deletions phpstan.neon.dist
Expand Up @@ -3,3 +3,6 @@ parameters:
paths:
- src
- test

ignoreErrors:
- '#.*OpenSSLAsymmetricKey.*#'
27 changes: 18 additions & 9 deletions src/Signer/OpenSSL.php
Expand Up @@ -5,10 +5,11 @@

use InvalidArgumentException;
use Lcobucci\JWT\Signer;
use OpenSSLAsymmetricKey;

use function assert;
use function is_array;
use function is_resource;
use function is_bool;
use function openssl_error_string;
use function openssl_free_key;
use function openssl_pkey_get_details;
Expand Down Expand Up @@ -37,16 +38,15 @@ final protected function createSignature(

return $signature;
} finally {
openssl_free_key($key);
$this->freeKey($key);
}
}

/** @return resource */
/** @return resource|OpenSSLAsymmetricKey */
private function getPrivateKey(string $pem, string $passphrase)
{
$privateKey = openssl_pkey_get_private($pem, $passphrase);
$this->validateKey($privateKey);
assert(is_resource($privateKey));

return $privateKey;
}
Expand All @@ -58,31 +58,30 @@ final protected function verifySignature(
): bool {
$key = $this->getPublicKey($pem);
$result = openssl_verify($payload, $expected, $key, $this->getAlgorithm());
openssl_free_key($key);
$this->freeKey($key);

return $result === 1;
}

/** @return resource */
/** @return resource|OpenSSLAsymmetricKey */
private function getPublicKey(string $pem)
{
$publicKey = openssl_pkey_get_public($pem);
$this->validateKey($publicKey);
assert(is_resource($publicKey));

return $publicKey;
}

/**
* Raises an exception when the key type is not the expected type
*
* @param resource|bool $key
* @param resource|OpenSSLAsymmetricKey|bool $key
*
* @throws InvalidArgumentException
*/
private function validateKey($key): void
{
if (! is_resource($key)) {
if (is_bool($key)) {
throw new InvalidArgumentException(
'It was not possible to parse your key, reason: ' . openssl_error_string()
);
Expand All @@ -96,6 +95,16 @@ private function validateKey($key): void
}
}

/** @param resource|OpenSSLAsymmetricKey $key */
private function freeKey($key): void
{
if ($key instanceof OpenSSLAsymmetricKey) {
return;
}

openssl_free_key($key); // Deprecated and no longer necessary as of PHP >= 8.0
}

/**
* Returns the type of key to be used to create/verify the signature (using OpenSSL constants)
*
Expand Down
8 changes: 5 additions & 3 deletions test/unit/Signer/EcdsaTest.php
Expand Up @@ -5,8 +5,11 @@

use Lcobucci\JWT\Keys;
use Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter;
use OpenSSLAsymmetricKey;
use PHPUnit\Framework\TestCase;

use function assert;
use function is_resource;
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function openssl_sign;
Expand Down Expand Up @@ -62,8 +65,8 @@ public function signShouldReturnTheAHashBasedOnTheOpenSslSignature(): void
$signature = $signer->sign($payload, self::$ecdsaKeys['private']);

$publicKey = openssl_pkey_get_public(self::$ecdsaKeys['public1']->getContent());
assert(is_resource($publicKey) || $publicKey instanceof OpenSSLAsymmetricKey);

self::assertIsResource($publicKey);
self::assertSame(
1,
openssl_verify(
Expand All @@ -90,8 +93,7 @@ public function verifyShouldDelegateToEcdsaSignerUsingPublicKey(): void
{
$payload = 'testing';
$privateKey = openssl_pkey_get_private(self::$ecdsaKeys['private']->getContent());

self::assertIsResource($privateKey);
assert(is_resource($privateKey) || $privateKey instanceof OpenSSLAsymmetricKey);

$signature = '';
openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
Expand Down
8 changes: 6 additions & 2 deletions test/unit/Signer/RsaTest.php
Expand Up @@ -5,8 +5,11 @@

use InvalidArgumentException;
use Lcobucci\JWT\Keys;
use OpenSSLAsymmetricKey;
use PHPUnit\Framework\TestCase;

use function assert;
use function is_resource;
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function openssl_sign;
Expand Down Expand Up @@ -36,7 +39,8 @@ public function signShouldReturnAValidOpensslSignature(): void
$signature = $signer->sign($payload, self::$rsaKeys['private']);

$publicKey = openssl_pkey_get_public(self::$rsaKeys['public']->getContent());
self::assertIsResource($publicKey);
assert(is_resource($publicKey) || $publicKey instanceof OpenSSLAsymmetricKey);

self::assertSame(1, openssl_verify($payload, $signature, $publicKey, OPENSSL_ALGO_SHA256));
}

Expand Down Expand Up @@ -117,7 +121,7 @@ public function verifyShouldReturnTrueWhenSignatureIsValid(): void
{
$payload = 'testing';
$privateKey = openssl_pkey_get_private(self::$rsaKeys['private']->getContent());
self::assertIsResource($privateKey);
assert(is_resource($privateKey) || $privateKey instanceof OpenSSLAsymmetricKey);

$signature = '';
openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
Expand Down

0 comments on commit be0f2f9

Please sign in to comment.