diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6f165ad..15605d5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "PHP", - "image": "mcr.microsoft.com/devcontainers/php:8.1-bullseye", + "image": "mcr.microsoft.com/devcontainers/php:8.2-bullseye", // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, diff --git a/composer.json b/composer.json index b5b82b7..fd45b24 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "require-dev": { "phpunit/phpunit": "^9.6 || ^10.0 || ^11.0", "consolidation/robo": "^4.0 || ^5.0", - "phpstan/phpstan": "^1.3.0", + "phpstan/phpstan": "^2.0.1", "phlak/semver": "^5.0 || ^6.0" }, "suggest": { diff --git a/composer.lock b/composer.lock index 175854e..28c907c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3126ba14863152346bcfbfb9ec84db8b", + "content-hash": "e7b31e0ef18faeafa1ce16fb9bb420c2", "packages": [], "packages-dev": [ { @@ -964,20 +964,20 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "384af967d35b2162f69526c7276acadce534d0e1" + "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/384af967d35b2162f69526c7276acadce534d0e1", - "reference": "384af967d35b2162f69526c7276acadce534d0e1", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d", + "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "php": "^7.4|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -1018,7 +1018,7 @@ "type": "github" } ], - "time": "2024-08-27T09:18:05+00:00" + "time": "2024-11-11T15:43:04+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 3ff6fa8..1edd4ad 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,4 +1,5 @@ parameters: level: 7 paths: - - src \ No newline at end of file + - src + treatPhpDocTypesAsCertain: false \ No newline at end of file diff --git a/src/SimpleJWT/Crypt/Encryption/AESGCM.php b/src/SimpleJWT/Crypt/Encryption/AESGCM.php index 5fd0aa0..42a1c2f 100644 --- a/src/SimpleJWT/Crypt/Encryption/AESGCM.php +++ b/src/SimpleJWT/Crypt/Encryption/AESGCM.php @@ -63,8 +63,6 @@ public function __construct(?string $alg) { * {@inheritdoc} */ public function getSupportedAlgs(): array { - if (!version_compare(PHP_VERSION, '7.1', '>=')) return []; - $ciphers = array_map('strtolower', openssl_get_cipher_methods()); $results = []; diff --git a/src/SimpleJWT/Crypt/KeyManagement/PBES2.php b/src/SimpleJWT/Crypt/KeyManagement/PBES2.php index a08ad83..93426b3 100644 --- a/src/SimpleJWT/Crypt/KeyManagement/PBES2.php +++ b/src/SimpleJWT/Crypt/KeyManagement/PBES2.php @@ -57,7 +57,7 @@ class PBES2 extends BaseAlgorithm implements KeyEncryptionAlgorithm { 'PBES2-HS512+A256KW' => ['hash' => 'sha512'] ]; - /** @var string $hash_alg */ + /** @var truthy-string $hash_alg */ protected $hash_alg; /** @var int $iterations */ @@ -162,8 +162,10 @@ protected function generateSaltInput(): string { */ private function generateKeyFromPassword(string $password, array $headers): string { $salt = $headers['alg'] . "\x00" . Util::base64url_decode($headers['p2s']); + /** @var int<0, max> $length */ + $length = intdiv($this->getAESKWKeySize(), 8); - return hash_pbkdf2($this->hash_alg, $password, $salt, $headers['p2c'], $this->getAESKWKeySize() / 8, true); + return hash_pbkdf2($this->hash_alg, $password, $salt, $headers['p2c'], $length, true); } } ?> diff --git a/src/SimpleJWT/Util/ASN1/Value.php b/src/SimpleJWT/Util/ASN1/Value.php index a99c937..fcaaa48 100644 --- a/src/SimpleJWT/Util/ASN1/Value.php +++ b/src/SimpleJWT/Util/ASN1/Value.php @@ -35,6 +35,7 @@ namespace SimpleJWT\Util\ASN1; +use \SimpleJWT\Util\Util; use \InvalidArgumentException; /** @@ -207,7 +208,7 @@ static public function oid(string $value): self { * @return Value */ static public function sequence(array $value): self { - if (!is_array($value)) { + if (!Util::array_is_list($value)) { throw new InvalidArgumentException('Not a sequence'); } return new self(static::SEQUENCE, $value); diff --git a/src/SimpleJWT/Util/BigNum.php b/src/SimpleJWT/Util/BigNum.php index 3ca37a9..02106f2 100644 --- a/src/SimpleJWT/Util/BigNum.php +++ b/src/SimpleJWT/Util/BigNum.php @@ -68,7 +68,7 @@ public function __construct($str = 0, int $base = 10) { $this->value = $value; return; default: - if (!is_integer($base) || ($base < 2) || ($base > 36)) + if (($base < 2) || ($base > 36)) throw new \InvalidArgumentException('$base cannot be less than 2 or greater than 36'); $value = (new BigNum(0))->value; diff --git a/src/SimpleJWT/Util/CBOR/CBOR.php b/src/SimpleJWT/Util/CBOR/CBOR.php index 510c7a1..e89ff3f 100644 --- a/src/SimpleJWT/Util/CBOR/CBOR.php +++ b/src/SimpleJWT/Util/CBOR/CBOR.php @@ -233,7 +233,7 @@ protected function decodeNext(string $data, int &$pos): ?DataItem { } break; default: - assert(true); + throw new CBORException('Invalid major type: expected list or map, got ' . ($major_type >> 5));; } } diff --git a/src/SimpleJWT/Util/CBOR/DataItem.php b/src/SimpleJWT/Util/CBOR/DataItem.php index 3aa8de3..6e0db05 100644 --- a/src/SimpleJWT/Util/CBOR/DataItem.php +++ b/src/SimpleJWT/Util/CBOR/DataItem.php @@ -123,7 +123,6 @@ class DataItem { * @param int $type the type * @param mixed $value the native PHP value * @param int $tag the tag number (i.e. excluding the class and constructed bit masks) - * @throws InvalidArgumentException */ function __construct(int $type, $value, int $tag = null) { $this->type = $type; @@ -233,7 +232,7 @@ static public function simple(int $value): self { * @return DataItem */ static public function list(array $value): self { - if (!is_array($value) || !self::array_is_list($value)) { + if (!Util::array_is_list($value)) { throw new InvalidArgumentException('Not an array'); } return new self(static::LIST_TYPE, $value); @@ -246,7 +245,7 @@ static public function list(array $value): self { * @return DataItem */ static public function map(array $value): self { - if (!is_array($value)|| self::array_is_list($value)) { + if (Util::array_is_list($value)) { throw new InvalidArgumentException('Not an associative array'); } return new self(static::MAP_TYPE, $value); @@ -260,7 +259,7 @@ static public function default($value): self { if ($value instanceof DataItem) { return $value; } elseif (is_array($value)) { - if (self::array_is_list($value)) { + if (Util::array_is_list($value)) { return static::list($value); } else { return static::map($value); @@ -424,19 +423,6 @@ protected function prettyPrint(int $indent = 0): string { public function __toString(): string { return $this->prettyPrint(); } - - /** - * Returns whether an array is a list. - * - * This is a polyfill for PHP 8.1's array_as_list function. - * - * @param array $array - * @return bool if the array is a list - */ - public static function array_is_list(array $array): bool { - if (function_exists('array_is_list')) return \array_is_list($array); - return $array === [] || (array_keys($array) === range(0, count($array) - 1)); - } } ?> diff --git a/src/SimpleJWT/Util/Util.php b/src/SimpleJWT/Util/Util.php index f7fd756..4f45379 100644 --- a/src/SimpleJWT/Util/Util.php +++ b/src/SimpleJWT/Util/Util.php @@ -120,11 +120,7 @@ static public function secure_compare(string $str1, string $str2): bool { */ static function packInt64(int $x): string { if (PHP_INT_SIZE == 8) { - if (version_compare(PHP_VERSION, '5.6.3', '>=')) { - return pack('J', $x); - } else { - return pack('NN', ($x & 0xFFFFFFFF00000000) >> 32, $x & ($x & 0x00000000FFFFFFFF)); - } + return pack('J', $x); } else { // 32-bit system return "\x00\x00\x00\x00" . pack('N', $x); @@ -143,6 +139,19 @@ static function packInt64(int $x): string { static function random_bytes(int $num_bytes): string { return random_bytes($num_bytes); } + + /** + * Returns whether an array is a list. + * + * This is a polyfill for PHP 8.1's array_as_list function. + * + * @param array $array + * @return bool if the array is a list + */ + public static function array_is_list(array $array): bool { + if (function_exists('array_is_list')) return \array_is_list($array); + return $array === [] || (array_keys($array) === range(0, count($array) - 1)); + } } ?>