M .gitignore => .gitignore +1 -0
@@ 1,2 1,3 @@
/vendor
/composer.lock
+/.php-cs-fixer.cache
R .php_cs.dist => .php-cs-fixer.dist.php +40 -39
@@ 1,44 1,45 @@
<?php
-return PhpCsFixer\Config::create()
- ->setRiskyAllowed(true)
- ->setRules(
- [
- '@Symfony' => true,
- '@Symfony:risky' => true,
- 'ordered_imports' => true,
- 'ordered_class_elements' => true,
- 'array_syntax' => ['syntax' => 'short'],
- 'native_function_invocation' => true,
- 'phpdoc_order' => true,
- 'phpdoc_no_empty_return' => false,
- 'phpdoc_add_missing_param_annotation' => true,
- 'strict_comparison' => true,
- 'strict_param' => true,
- 'php_unit_strict' => true,
- 'header_comment' => [
- 'header' => <<< 'EOD'
-Copyright (c) 2019-2020 François Kooman <fkooman@tuxed.net>
+$config = new PhpCsFixer\Config();
+
+return $config->setRules(
+ [
+ '@PSR12' => true,
+ 'visibility_required' => ['elements' => ['method', 'property']],
+ 'ordered_imports' => true,
+ 'ordered_class_elements' => true,
+ 'array_syntax' => ['syntax' => 'short'],
+ 'phpdoc_order' => true,
+ 'phpdoc_no_empty_return' => false,
+ 'phpdoc_add_missing_param_annotation' => true,
+ 'strict_comparison' => true,
+ 'strict_param' => true,
+ 'php_unit_strict' => true,
+ 'header_comment' => [
+ 'header' => <<< 'EOD'
+ Copyright (c) 2019-2020 François Kooman <fkooman@tuxed.net>
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-EOD
- ],
- ]
- )
- ->setFinder(PhpCsFixer\Finder::create()->in(__DIR__));
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ EOD,
+ ],
+ ]
+)
+ ->setRiskyAllowed(true)
+ ->setFinder(PhpCsFixer\Finder::create()->in(__DIR__))
+;
A Makefile => Makefile +18 -0
@@ 0,0 1,18 @@
+.PHONY: all test fmt psalm phpstan sloc
+
+all: test fmt psalm phpstan
+
+test:
+ vendor/bin/put
+
+fmt:
+ php-cs-fixer fix
+
+psalm:
+ psalm
+
+phpstan:
+ phpstan
+
+sloc:
+ phploc src
M composer.json => composer.json +14 -4
@@ 2,7 2,7 @@
"authors": [
{
"email": "fkooman@tuxed.net",
- "name": "Fran\u00e7ois Kooman"
+ "name": "François Kooman"
}
],
"autoload": {
@@ 15,23 15,33 @@
"fkooman\\Jwt\\Tests\\": "tests/"
}
},
+ "config": {
+ "platform": {
+ "php": "5.4.8"
+ }
+ },
"description": "Small JSON Web Signature implementation",
"license": "MIT",
"name": "fkooman/jwt",
+ "repositories": [
+ {
+ "type": "vcs",
+ "url": "https://git.sr.ht/~fkooman/put"
+ }
+ ],
"require": {
"ext-date": "*",
"ext-hash": "*",
"ext-json": "*",
"ext-openssl": "*",
"ext-spl": "*",
- "paragonie/constant_time_encoding": "^1.0.3|^2.2.0",
- "paragonie/random_compat": ">=1",
+ "paragonie/random_compat": "^2",
"paragonie/sodium_compat": "^1",
"php": ">= 5.4.8",
"symfony/polyfill-php56": "^1"
},
"require-dev": {
- "phpunit/phpunit": "^4|^5|^6|^7"
+ "fkooman/put": "^0"
},
"support": {
"email": "fkooman@tuxed.net",
D phpunit.xml.dist => phpunit.xml.dist +0 -21
@@ 1,21 0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.3/phpunit.xsd"
- bootstrap="vendor/autoload.php"
- forceCoversAnnotation="false"
- beStrictAboutCoversAnnotation="true"
- beStrictAboutOutputDuringTests="true"
- beStrictAboutTodoAnnotatedTests="true"
- verbose="true">
- <testsuites>
- <testsuite name="default">
- <directory suffix="Test.php">tests</directory>
- </testsuite>
- </testsuites>
-
- <filter>
- <whitelist processUncoveredFilesFromWhitelist="true">
- <directory suffix=".php">src</directory>
- </whitelist>
- </filter>
-</phpunit>
A src/Base64UrlSafe.php => src/Base64UrlSafe.php +46 -0
@@ 0,0 1,46 @@
+<?php
+
+/*
+ * Copyright (c) 2019-2020 François Kooman <fkooman@tuxed.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace fkooman\Jwt;
+
+class Base64UrlSafe
+{
+ /**
+ * @param string $inputStr
+ * @return string
+ */
+ public static function encodeUnpadded($inputStr)
+ {
+ return sodium_bin2base64($inputStr, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
+ }
+
+ /**
+ * @param string $inputStr
+ * @return string
+ */
+ public static function decode($inputStr)
+ {
+ return sodium_base642bin($inputStr, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
+ }
+}
M src/Jwt.php => src/Jwt.php +0 -1
@@ 26,7 26,6 @@ namespace fkooman\Jwt;
use DateTime;
use fkooman\Jwt\Exception\JwtException;
-use ParagonIE\ConstantTime\Base64UrlSafe;
/**
* The base class that MUST be extended by the classes that actually implement
M src/Keys/EdDSA/PublicKey.php => src/Keys/EdDSA/PublicKey.php +2 -3
@@ 24,9 24,8 @@
namespace fkooman\Jwt\Keys\EdDSA;
+use fkooman\Jwt\Base64UrlSafe;
use LengthException;
-use ParagonIE\ConstantTime\Base64UrlSafe;
-use ParagonIE\ConstantTime\Binary;
class PublicKey
{
@@ 38,7 37,7 @@ class PublicKey
*/
public function __construct($publicKey)
{
- if (SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES !== Binary::safeStrlen($publicKey)) {
+ if (SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES !== strlen($publicKey)) {
throw new LengthException('invalid public key length');
}
$this->publicKey = $publicKey;
M src/Keys/EdDSA/SecretKey.php => src/Keys/EdDSA/SecretKey.php +4 -5
@@ 24,8 24,7 @@
namespace fkooman\Jwt\Keys\EdDSA;
-use ParagonIE\ConstantTime\Base64UrlSafe;
-use ParagonIE\ConstantTime\Binary;
+use fkooman\Jwt\Base64UrlSafe;
class SecretKey
{
@@ 37,15 36,15 @@ class SecretKey
*/
public function __construct($secretKey)
{
- switch (Binary::safeStrlen($secretKey)) {
+ switch (strlen($secretKey)) {
case SODIUM_CRYPTO_SIGN_SECRETKEYBYTES:
$this->secretKey = $secretKey;
break;
case SODIUM_CRYPTO_SIGN_SEEDBYTES:
- $this->secretKey = Binary::safeSubstr(\sodium_crypto_sign_seed_keypair($secretKey), 0, 64);
+ $this->secretKey = substr(\sodium_crypto_sign_seed_keypair($secretKey), 0, 64);
break;
case SODIUM_CRYPTO_SIGN_KEYPAIRBYTES:
- $this->secretKey = Binary::safeSubstr($secretKey, 0, 64);
+ $this->secretKey = substr($secretKey, 0, 64);
break;
default:
throw new \LengthException('invalid secret key length');
M src/Keys/HS256/SecretKey.php => src/Keys/HS256/SecretKey.php +3 -3
@@ 24,9 24,9 @@
namespace fkooman\Jwt\Keys\HS256;
+use fkooman\Jwt\Base64UrlSafe;
+
use fkooman\Jwt\Exception\KeyException;
-use ParagonIE\ConstantTime\Base64UrlSafe;
-use ParagonIE\ConstantTime\Binary;
class SecretKey
{
@@ 41,7 41,7 @@ class SecretKey
*/
public function __construct($secretKey)
{
- if (32 !== Binary::safeStrlen($secretKey)) {
+ if (32 !== strlen($secretKey)) {
throw new KeyException('invalid key length');
}
$this->secretKey = $secretKey;
M src/Keys/RS256/PrivateKey.php => src/Keys/RS256/PrivateKey.php +1 -2
@@ 25,7 25,6 @@
namespace fkooman\Jwt\Keys\RS256;
use fkooman\Jwt\Exception\KeyException;
-use ParagonIE\ConstantTime\Binary;
use RuntimeException;
class PrivateKey
@@ 52,7 51,7 @@ class PrivateKey
$rsaInfo = $keyInfo['rsa'];
// RSA key MUST be at least 2048 bits
// @see https://tools.ietf.org/html/rfc7518#section-4.2
- if (256 > Binary::safeStrlen($rsaInfo['n'])) {
+ if (256 > strlen($rsaInfo['n'])) {
throw new KeyException('invalid RSA key, must be >= 2048 bits');
}
$this->privateKey = $privateKey;
M tests/EdDSATest.php => tests/EdDSATest.php +5 -6
@@ 24,11 24,10 @@
namespace fkooman\Jwt\Tests;
+use fkooman\Jwt\Base64UrlSafe;
use fkooman\Jwt\EdDSA;
use fkooman\Jwt\Keys\EdDSA\PublicKey;
use fkooman\Jwt\Keys\EdDSA\SecretKey;
-use ParagonIE\ConstantTime\Base64UrlSafe;
-use ParagonIE\ConstantTime\Hex;
use PHPUnit\Framework\TestCase;
class EdDSATest extends TestCase
@@ 71,14 70,14 @@ class EdDSATest extends TestCase
public function testKeys()
{
- $secretKey = new SecretKey(Hex::decode('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'));
- $publicKey = new PublicKey(Hex::decode('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'));
+ $secretKey = new SecretKey(hex2bin('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'));
+ $publicKey = new PublicKey(hex2bin('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'));
$this->assertSame($secretKey->getPublicKey()->encode(), $publicKey->encode());
}
public function testTestVectorSign()
{
- $secretKey = new SecretKey(Hex::decode('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'));
+ $secretKey = new SecretKey(hex2bin('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'));
$dsa = new TestEdDSA(
$secretKey->getPublicKey(),
$secretKey
@@ 88,7 87,7 @@ class EdDSATest extends TestCase
public function testTestVectorVerify()
{
- $publicKey = new PublicKey(Hex::decode('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'));
+ $publicKey = new PublicKey(hex2bin('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'));
$dsa = new TestEdDSA($publicKey);
$this->assertTrue(
$dsa->verify(