diff --git a/.gitattributes b/.gitattributes index c682f861..a791521e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,4 +5,3 @@ /.gitignore export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore -/run-tests.sh export-ignore diff --git a/.travis.yml b/.travis.yml index fc651ad3..90e516cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ language: php +branches: + - only: [master] + php: - 5.6 - 7.0 @@ -16,8 +19,18 @@ matrix: dist: trusty - php: 5.5 dist: trusty + - name: "Check Style" + php: "7.4" + env: RUN_CS_FIXER=true sudo: false before_script: composer install -script: vendor/bin/phpunit +script: + - if [ "${RUN_CS_FIXER}" = "true" ]; then + composer require friendsofphp/php-cs-fixer && + vendor/bin/php-cs-fixer fix --diff --dry-run . && + vendor/bin/php-cs-fixer fix --rules=native_function_invocation --allow-risky=yes --diff src; + else + vendor/bin/phpunit; + fi diff --git a/run-tests.sh b/run-tests.sh deleted file mode 100755 index c4bb9348..00000000 --- a/run-tests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -gpg --fingerprint D8406D0D82947747293778314AA394086372C20A -if [ $? -ne 0 ]; then - echo -e "\033[33mDownloading PGP Public Key...\033[0m" - gpg --recv-keys D8406D0D82947747293778314AA394086372C20A - # Sebastian Bergmann - gpg --fingerprint D8406D0D82947747293778314AA394086372C20A - if [ $? -ne 0 ]; then - echo -e "\033[31mCould not download PGP public key for verification\033[0m" - exit - fi -fi - -# Let's grab the latest release and its signature -if [ ! -f phpunit.phar ]; then - wget https://phar.phpunit.de/phpunit.phar -fi -if [ ! -f phpunit.phar.asc ]; then - wget https://phar.phpunit.de/phpunit.phar.asc -fi - -# Verify before running -gpg --verify phpunit.phar.asc phpunit.phar -if [ $? -eq 0 ]; then - echo - echo -e "\033[33mBegin Unit Testing\033[0m" - # Run the testing suite - php --version - php phpunit.phar --configuration phpunit.xml.dist -else - echo - chmod -x phpunit.phar - mv phpunit.phar /tmp/bad-phpunit.phar - mv phpunit.phar.asc /tmp/bad-phpunit.phar.asc - echo -e "\033[31mSignature did not match! PHPUnit has been moved to /tmp/bad-phpunit.phar\033[0m" - exit 1 -fi diff --git a/src/BeforeValidException.php b/src/BeforeValidException.php index a6ee2f7c..fdf82bd9 100644 --- a/src/BeforeValidException.php +++ b/src/BeforeValidException.php @@ -3,5 +3,4 @@ class BeforeValidException extends \UnexpectedValueException { - } diff --git a/src/ExpiredException.php b/src/ExpiredException.php index 3597370a..7f7d0568 100644 --- a/src/ExpiredException.php +++ b/src/ExpiredException.php @@ -3,5 +3,4 @@ class ExpiredException extends \UnexpectedValueException { - } diff --git a/src/JWK.php b/src/JWK.php index f2777df8..1d273917 100644 --- a/src/JWK.php +++ b/src/JWK.php @@ -50,7 +50,7 @@ public static function parseKeySet(array $jwks) } } - if (0 === count($keys)) { + if (0 === \count($keys)) { throw new UnexpectedValueException('No supported algorithms found in JWK Set'); } @@ -81,7 +81,7 @@ private static function parseKey(array $jwk) switch ($jwk['kty']) { case 'RSA': - if (array_key_exists('d', $jwk)) { + if (\array_key_exists('d', $jwk)) { throw new UnexpectedValueException('RSA private keys are not supported'); } if (!isset($jwk['n']) || !isset($jwk['e'])) { @@ -89,10 +89,10 @@ private static function parseKey(array $jwk) } $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']); - $publicKey = openssl_pkey_get_public($pem); + $publicKey = \openssl_pkey_get_public($pem); if (false === $publicKey) { throw new DomainException( - 'OpenSSL error: ' . openssl_error_string() + 'OpenSSL error: ' . \openssl_error_string() ); } return $publicKey; @@ -118,32 +118,32 @@ private static function createPemFromModulusAndExponent($n, $e) $publicExponent = JWT::urlsafeB64Decode($e); $components = array( - 'modulus' => pack('Ca*a*', 2, self::encodeLength(strlen($modulus)), $modulus), - 'publicExponent' => pack('Ca*a*', 2, self::encodeLength(strlen($publicExponent)), $publicExponent) + 'modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus), + 'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent) ); - $rsaPublicKey = pack( + $rsaPublicKey = \pack( 'Ca*a*a*', 48, - self::encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), + self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent'] ); // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. - $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA - $rsaPublicKey = chr(0) . $rsaPublicKey; - $rsaPublicKey = chr(3) . self::encodeLength(strlen($rsaPublicKey)) . $rsaPublicKey; + $rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA + $rsaPublicKey = \chr(0) . $rsaPublicKey; + $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey; - $rsaPublicKey = pack( + $rsaPublicKey = \pack( 'Ca*a*', 48, - self::encodeLength(strlen($rsaOID . $rsaPublicKey)), + self::encodeLength(\strlen($rsaOID . $rsaPublicKey)), $rsaOID . $rsaPublicKey ); $rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(base64_encode($rsaPublicKey), 64) . + \chunk_split(\base64_encode($rsaPublicKey), 64) . '-----END PUBLIC KEY-----'; return $rsaPublicKey; @@ -161,11 +161,11 @@ private static function createPemFromModulusAndExponent($n, $e) private static function encodeLength($length) { if ($length <= 0x7F) { - return chr($length); + return \chr($length); } - $temp = ltrim(pack('N', $length), chr(0)); + $temp = \ltrim(\pack('N', $length), \chr(0)); - return pack('Ca*', 0x80 | strlen($temp), $temp); + return \pack('Ca*', 0x80 | \strlen($temp), $temp); } } diff --git a/src/JWT.php b/src/JWT.php index 6f178b4e..4860028b 100644 --- a/src/JWT.php +++ b/src/JWT.php @@ -73,13 +73,13 @@ class JWT */ public static function decode($jwt, $key, array $allowed_algs = array()) { - $timestamp = is_null(static::$timestamp) ? time() : static::$timestamp; + $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp; if (empty($key)) { throw new InvalidArgumentException('Key may not be empty'); } - $tks = explode('.', $jwt); - if (count($tks) != 3) { + $tks = \explode('.', $jwt); + if (\count($tks) != 3) { throw new UnexpectedValueException('Wrong number of segments'); } list($headb64, $bodyb64, $cryptob64) = $tks; @@ -98,7 +98,7 @@ public static function decode($jwt, $key, array $allowed_algs = array()) if (empty(static::$supported_algs[$header->alg])) { throw new UnexpectedValueException('Algorithm not supported'); } - if (!in_array($header->alg, $allowed_algs)) { + if (!\in_array($header->alg, $allowed_algs)) { throw new UnexpectedValueException('Algorithm not allowed'); } if ($header->alg === 'ES256') { @@ -106,7 +106,7 @@ public static function decode($jwt, $key, array $allowed_algs = array()) $sig = self::signatureToDER($sig); } - if (is_array($key) || $key instanceof \ArrayAccess) { + if (\is_array($key) || $key instanceof \ArrayAccess) { if (isset($header->kid)) { if (!isset($key[$header->kid])) { throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key'); @@ -126,7 +126,7 @@ public static function decode($jwt, $key, array $allowed_algs = array()) // token can actually be used. If it's not yet that time, abort. if (isset($payload->nbf) && $payload->nbf > ($timestamp + static::$leeway)) { throw new BeforeValidException( - 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf) + 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->nbf) ); } @@ -135,7 +135,7 @@ public static function decode($jwt, $key, array $allowed_algs = array()) // correctly used the nbf claim). if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) { throw new BeforeValidException( - 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat) + 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat) ); } @@ -169,18 +169,18 @@ public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $he if ($keyId !== null) { $header['kid'] = $keyId; } - if (isset($head) && is_array($head)) { - $header = array_merge($head, $header); + if (isset($head) && \is_array($head)) { + $header = \array_merge($head, $header); } $segments = array(); $segments[] = static::urlsafeB64Encode(static::jsonEncode($header)); $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload)); - $signing_input = implode('.', $segments); + $signing_input = \implode('.', $segments); $signature = static::sign($signing_input, $key, $alg); $segments[] = static::urlsafeB64Encode($signature); - return implode('.', $segments); + return \implode('.', $segments); } /** @@ -203,10 +203,10 @@ public static function sign($msg, $key, $alg = 'HS256') list($function, $algorithm) = static::$supported_algs[$alg]; switch ($function) { case 'hash_hmac': - return hash_hmac($algorithm, $msg, $key, true); + return \hash_hmac($algorithm, $msg, $key, true); case 'openssl': $signature = ''; - $success = openssl_sign($msg, $signature, $key, $algorithm); + $success = \openssl_sign($msg, $signature, $key, $algorithm); if (!$success) { throw new DomainException("OpenSSL unable to sign data"); } else { @@ -240,7 +240,7 @@ private static function verify($msg, $signature, $key, $alg) list($function, $algorithm) = static::$supported_algs[$alg]; switch ($function) { case 'openssl': - $success = openssl_verify($msg, $signature, $key, $algorithm); + $success = \openssl_verify($msg, $signature, $key, $algorithm); if ($success === 1) { return true; } elseif ($success === 0) { @@ -248,19 +248,19 @@ private static function verify($msg, $signature, $key, $alg) } // returns 1 on success, 0 on failure, -1 on error. throw new DomainException( - 'OpenSSL error: ' . openssl_error_string() + 'OpenSSL error: ' . \openssl_error_string() ); case 'hash_hmac': default: - $hash = hash_hmac($algorithm, $msg, $key, true); - if (function_exists('hash_equals')) { - return hash_equals($signature, $hash); + $hash = \hash_hmac($algorithm, $msg, $key, true); + if (\function_exists('hash_equals')) { + return \hash_equals($signature, $hash); } - $len = min(static::safeStrlen($signature), static::safeStrlen($hash)); + $len = \min(static::safeStrlen($signature), static::safeStrlen($hash)); $status = 0; for ($i = 0; $i < $len; $i++) { - $status |= (ord($signature[$i]) ^ ord($hash[$i])); + $status |= (\ord($signature[$i]) ^ \ord($hash[$i])); } $status |= (static::safeStrlen($signature) ^ static::safeStrlen($hash)); @@ -279,23 +279,23 @@ private static function verify($msg, $signature, $key, $alg) */ public static function jsonDecode($input) { - if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) { + if (\version_compare(PHP_VERSION, '5.4.0', '>=') && !(\defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) { /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you * to specify that large ints (like Steam Transaction IDs) should be treated as * strings, rather than the PHP default behaviour of converting them to floats. */ - $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING); + $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING); } else { /** Not all servers will support that, however, so for older versions we must * manually detect large ints in the JSON string and quote them (thus converting *them to strings) before decoding, hence the preg_replace() call. */ - $max_int_length = strlen((string) PHP_INT_MAX) - 1; - $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input); - $obj = json_decode($json_without_bigints); + $max_int_length = \strlen((string) PHP_INT_MAX) - 1; + $json_without_bigints = \preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input); + $obj = \json_decode($json_without_bigints); } - if ($errno = json_last_error()) { + if ($errno = \json_last_error()) { static::handleJsonError($errno); } elseif ($obj === null && $input !== 'null') { throw new DomainException('Null result with non-null input'); @@ -314,8 +314,8 @@ public static function jsonDecode($input) */ public static function jsonEncode($input) { - $json = json_encode($input); - if ($errno = json_last_error()) { + $json = \json_encode($input); + if ($errno = \json_last_error()) { static::handleJsonError($errno); } elseif ($json === 'null' && $input !== null) { throw new DomainException('Null result with non-null input'); @@ -332,12 +332,12 @@ public static function jsonEncode($input) */ public static function urlsafeB64Decode($input) { - $remainder = strlen($input) % 4; + $remainder = \strlen($input) % 4; if ($remainder) { $padlen = 4 - $remainder; - $input .= str_repeat('=', $padlen); + $input .= \str_repeat('=', $padlen); } - return base64_decode(strtr($input, '-_', '+/')); + return \base64_decode(\strtr($input, '-_', '+/')); } /** @@ -349,7 +349,7 @@ public static function urlsafeB64Decode($input) */ public static function urlsafeB64Encode($input) { - return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); + return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_')); } /** @@ -384,10 +384,10 @@ private static function handleJsonError($errno) */ private static function safeStrlen($str) { - if (function_exists('mb_strlen')) { - return mb_strlen($str, '8bit'); + if (\function_exists('mb_strlen')) { + return \mb_strlen($str, '8bit'); } - return strlen($str); + return \strlen($str); } /** @@ -399,18 +399,18 @@ private static function safeStrlen($str) private static function signatureToDER($sig) { // Separate the signature into r-value and s-value - list($r, $s) = str_split($sig, (int) (strlen($sig) / 2)); + list($r, $s) = \str_split($sig, (int) (\strlen($sig) / 2)); // Trim leading zeros - $r = ltrim($r, "\x00"); - $s = ltrim($s, "\x00"); + $r = \ltrim($r, "\x00"); + $s = \ltrim($s, "\x00"); // Convert r-value and s-value from unsigned big-endian integers to // signed two's complement - if (ord($r[0]) > 0x7f) { + if (\ord($r[0]) > 0x7f) { $r = "\x00" . $r; } - if (ord($s[0]) > 0x7f) { + if (\ord($s[0]) > 0x7f) { $s = "\x00" . $s; } @@ -436,10 +436,10 @@ private static function encodeDER($type, $value) } // Type - $der = chr($tag_header | $type); + $der = \chr($tag_header | $type); // Length - $der .= chr(strlen($value)); + $der .= \chr(\strlen($value)); return $der . $value; } @@ -460,12 +460,12 @@ private static function signatureFromDER($der, $keySize) // Convert r-value and s-value from signed two's compliment to unsigned // big-endian integers - $r = ltrim($r, "\x00"); - $s = ltrim($s, "\x00"); + $r = \ltrim($r, "\x00"); + $s = \ltrim($s, "\x00"); // Pad out r and s so that they are $keySize bits long - $r = str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT); - $s = str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT); + $r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT); + $s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT); return $r . $s; } @@ -481,27 +481,27 @@ private static function signatureFromDER($der, $keySize) private static function readDER($der, $offset = 0) { $pos = $offset; - $size = strlen($der); - $constructed = (ord($der[$pos]) >> 5) & 0x01; - $type = ord($der[$pos++]) & 0x1f; + $size = \strlen($der); + $constructed = (\ord($der[$pos]) >> 5) & 0x01; + $type = \ord($der[$pos++]) & 0x1f; // Length - $len = ord($der[$pos++]); + $len = \ord($der[$pos++]); if ($len & 0x80) { $n = $len & 0x1f; $len = 0; while ($n-- && $pos < $size) { - $len = ($len << 8) | ord($der[$pos++]); + $len = ($len << 8) | \ord($der[$pos++]); } } // Value if ($type == self::ASN1_BIT_STRING) { $pos++; // Skip the first contents octet (padding indicator) - $data = substr($der, $pos, $len - 1); + $data = \substr($der, $pos, $len - 1); $pos += $len - 1; } elseif (!$constructed) { - $data = substr($der, $pos, $len); + $data = \substr($der, $pos, $len); $pos += $len; } else { $data = null; diff --git a/src/SignatureInvalidException.php b/src/SignatureInvalidException.php index 27332b21..87cb34df 100644 --- a/src/SignatureInvalidException.php +++ b/src/SignatureInvalidException.php @@ -3,5 +3,4 @@ class SignatureInvalidException extends \UnexpectedValueException { - } diff --git a/tests/JWKTest.php b/tests/JWKTest.php index d02534f1..3d317d55 100644 --- a/tests/JWKTest.php +++ b/tests/JWKTest.php @@ -88,7 +88,7 @@ public function testDecodeByMultiJwkKeySet() /* * For compatibility with PHPUnit 4.8 and PHP < 5.6 */ - public function setExpectedException($exceptionName, $message = '', $code = NULL) + public function setExpectedException($exceptionName, $message = '', $code = null) { if (method_exists($this, 'expectException')) { $this->expectException($exceptionName); diff --git a/tests/JWTTest.php b/tests/JWTTest.php index 867d87e5..fc9c3756 100644 --- a/tests/JWTTest.php +++ b/tests/JWTTest.php @@ -6,12 +6,11 @@ class JWTTest extends TestCase { - public static $opensslVerifyReturnValue; - /* * For compatibility with PHPUnit 4.8 and PHP < 5.6 */ - public function setExpectedException($exceptionName, $message = '', $code = NULL) { + public function setExpectedException($exceptionName, $message = '', $code = null) + { if (method_exists($this, 'expectException')) { $this->expectException($exceptionName); } else { @@ -285,15 +284,6 @@ public function testInvalidSignatureEncoding() JWT::decode($msg, 'secret', array('HS256')); } - public function testVerifyError() - { - $this->setExpectedException('DomainException'); - $pkey = openssl_pkey_new(); - $msg = JWT::encode('abc', $pkey, 'RS256'); - self::$opensslVerifyReturnValue = -1; - JWT::decode($msg, $pkey, array('RS256')); - } - /** * @runInSeparateProcess */ @@ -310,14 +300,3 @@ public function testEncodeAndDecodeEcdsaToken() $this->assertEquals('bar', $decoded->foo); } } - -/* - * Allows the testing of openssl_verify with an error return value - */ -function openssl_verify($msg, $signature, $key, $algorithm) -{ - if (null !== JWTTest::$opensslVerifyReturnValue) { - return JWTTest::$opensslVerifyReturnValue; - } - return \openssl_verify($msg, $signature, $key, $algorithm); -}