Skip to content

Commit 7333842

Browse files
committed
:octocat: use chillerlan/php-standard-utilities
1 parent f8c4dbe commit 7333842

12 files changed

+52
-207
lines changed

composer.json

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://getcomposer.org/schema.json",
23
"name": "chillerlan/php-oauth",
34
"description": "A fully transparent, framework agnostic PSR-18 OAuth client.",
45
"homepage": "https://github.com/chillerlan/php-oauth",
@@ -36,6 +37,7 @@
3637
"ext-sodium": "*",
3738
"chillerlan/php-http-message-utils": "^2.2.2",
3839
"chillerlan/php-settings-container": "^3.2.1",
40+
"chillerlan/php-standard-utilities": "^1.0",
3941
"psr/http-client": "^1.0",
4042
"psr/http-message": "^1.1 || ^2.0",
4143
"psr/log": "^1.1 || ^2.0 || ^3.0"

phpstan-baseline.neon

-5
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@ parameters:
2020
count: 1
2121
path: src/Core/OAuthProvider.php
2222

23-
-
24-
message: "#^Parameter \\#1 \\$content of method Psr\\\\Http\\\\Message\\\\StreamFactoryInterface\\:\\:createStream\\(\\) expects string, string\\|false given\\.$#"
25-
count: 1
26-
path: src/Core/OAuthProvider.php
27-
2823
-
2924
message: "#^Parameter \\#1 \\$length of function random_bytes expects int\\<1, max\\>, int given\\.$#"
3025
count: 1

phpstan.dist.neon

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ parameters:
1313
# see https://github.com/phpstan/phpstan-src/blob/1.8.x/build/ignore-by-php-version.neon.php
1414
includes:
1515
- phpstan-baseline.neon
16-
- .phpstan/ignore-by-php-version.php
1716
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
1817
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
1918
- vendor/chillerlan/php-settings-container/rules-magic-access.neon

src/Core/OAuth1Provider.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
use chillerlan\HTTP\Utils\{MessageUtil, QueryUtil};
1717
use chillerlan\OAuth\Providers\ProviderException;
18+
use chillerlan\Utilities\Str;
1819
use Psr\Http\Message\{RequestInterface, ResponseInterface, UriInterface};
19-
use function array_merge, hash_hmac, implode, in_array, sodium_bin2base64, sprintf, strtoupper, time;
20-
use const SODIUM_BASE64_VARIANT_ORIGINAL;
20+
use function array_merge, hash_hmac, implode, in_array, sprintf, strtoupper, time;
2121

2222
/**
2323
* Implements an abstract OAuth1 (1.0a) provider with all methods required by the OAuth1Interface.
@@ -186,7 +186,7 @@ protected function getSignature(
186186

187187
$hash = hash_hmac('sha1', implode('&', $data), implode('&', $key), true);
188188

189-
return sodium_bin2base64($hash, SODIUM_BASE64_VARIANT_ORIGINAL);
189+
return Str::base64encode($hash);
190190
}
191191

192192
/**

src/Core/OAuthProvider.php

+7-7
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@
1818
use chillerlan\OAuth\Providers\ProviderException;
1919
use chillerlan\OAuth\Storage\{MemoryStorage, OAuthStorageInterface};
2020
use chillerlan\Settings\SettingsContainerInterface;
21+
use chillerlan\Utilities\Str;
2122
use Psr\Http\Client\ClientInterface;
2223
use Psr\Http\Message\{
2324
RequestFactoryInterface, RequestInterface, ResponseInterface,
2425
StreamFactoryInterface, StreamInterface, UriFactoryInterface
2526
};
2627
use Psr\Log\{LoggerInterface, NullLogger};
27-
use ReflectionClass, UnhandledMatchError;
28-
use function array_merge, array_shift, explode, implode, in_array, is_array, is_string,
29-
json_encode, ltrim, random_bytes, rtrim, sodium_bin2hex, sodium_bin2base64,
30-
sprintf, str_contains, str_starts_with, strip_tags, strtolower;
31-
use const PHP_QUERY_RFC1738, SODIUM_BASE64_VARIANT_ORIGINAL;
28+
use ReflectionClass;
29+
use function array_merge, array_shift, explode, implode, in_array, is_array, is_string, ltrim,
30+
random_bytes, rtrim, sodium_bin2hex, sprintf, str_contains, str_starts_with, strip_tags, strtolower;
31+
use const PHP_QUERY_RFC1738;
3232

3333
/**
3434
* Implements an abstract OAuth provider with all methods required by the OAuthInterface.
@@ -271,7 +271,7 @@ protected function cleanBodyParams(iterable $params):array{
271271
* Adds an "Authorization: Basic <base64(key:secret)>" header to the given request
272272
*/
273273
protected function addBasicAuthHeader(RequestInterface $request):RequestInterface{
274-
$auth = sodium_bin2base64(sprintf('%s:%s', $this->options->key, $this->options->secret), SODIUM_BASE64_VARIANT_ORIGINAL);
274+
$auth = Str::base64encode(sprintf('%s:%s', $this->options->key, $this->options->secret));
275275

276276
return $request->withHeader('Authorization', sprintf('Basic %s', $auth));
277277
}
@@ -363,7 +363,7 @@ final protected function setRequestBody(StreamInterface|array|string $body, Requ
363363

364364
$body = match($contentType){
365365
'application/x-www-form-urlencoded' => QueryUtil::build($body, PHP_QUERY_RFC1738),
366-
'application/json', 'application/vnd.api+json' => json_encode($body),
366+
'application/json', 'application/vnd.api+json' => Str::jsonEncode($body, 0),
367367
default => throw new ProviderException(
368368
sprintf('invalid content-type "%s" for the given array body', $contentType),
369369
),

src/Core/PKCETrait.php

+4-25
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@
1212
namespace chillerlan\OAuth\Core;
1313

1414
use chillerlan\OAuth\Providers\ProviderException;
15-
use function hash;
16-
use function random_int;
17-
use function sodium_bin2base64;
18-
use const PHP_VERSION_ID;
15+
use chillerlan\Utilities\{Crypto, Str};
1916
use const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING;
2017

2118
/**
@@ -78,27 +75,9 @@ final public function setCodeVerifier(array $params):array{
7875
*
7976
* @see \chillerlan\OAuth\Core\PKCE::generateVerifier()
8077
* @see \chillerlan\OAuth\Core\OAuth2Provider::setCodeChallenge()
81-
*
82-
* @noinspection PhpFullyQualifiedNameUsageInspection
83-
* @SuppressWarnings(PHPMD.MissingImport)
8478
*/
8579
final public function generateVerifier(int $length):string{
86-
87-
// use the Randomizer if available
88-
// https://github.com/phpstan/phpstan/issues/7843
89-
if(PHP_VERSION_ID >= 80300){
90-
$randomizer = new \Random\Randomizer(new \Random\Engine\Secure);
91-
92-
return $randomizer->getBytesFromString(PKCE::VERIFIER_CHARSET, $length);
93-
}
94-
95-
$str = '';
96-
97-
for($i = 0; $i < $length; $i++){
98-
$str .= PKCE::VERIFIER_CHARSET[random_int(0, 65)];
99-
}
100-
101-
return $str;
80+
return Crypto::randomString($length, PKCE::VERIFIER_CHARSET);
10281
}
10382

10483
/**
@@ -114,12 +93,12 @@ final public function generateChallenge(string $verifier, string $challengeMetho
11493
}
11594

11695
$verifier = match($challengeMethod){
117-
PKCE::CHALLENGE_METHOD_S256 => hash('sha256', $verifier, true),
96+
PKCE::CHALLENGE_METHOD_S256 => Crypto::sha256($verifier, true),
11897
// no other hash methods yet
11998
default => throw new ProviderException('invalid PKCE challenge method'), // @codeCoverageIgnore
12099
};
121100

122-
return sodium_bin2base64($verifier, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
101+
return Str::base64encode($verifier, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
123102
}
124103

125104
}

src/Core/Utilities.php

+2-88
Original file line numberDiff line numberDiff line change
@@ -13,49 +13,29 @@
1313

1414
namespace chillerlan\OAuth\Core;
1515

16+
use chillerlan\Utilities\File;
1617
use DirectoryIterator;
1718
use InvalidArgumentException;
1819
use ReflectionClass;
19-
use RuntimeException;
2020
use function hash;
21-
use function random_bytes;
22-
use function realpath;
23-
use function sodium_base642bin;
24-
use function sodium_bin2base64;
25-
use function sodium_bin2hex;
26-
use function sodium_crypto_secretbox;
27-
use function sodium_crypto_secretbox_keygen;
28-
use function sodium_crypto_secretbox_open;
29-
use function sodium_hex2bin;
30-
use function sodium_memzero;
3121
use function substr;
3222
use function trim;
33-
use const SODIUM_BASE64_VARIANT_ORIGINAL;
34-
use const SODIUM_CRYPTO_SECRETBOX_NONCEBYTES;
3523

3624
/**
3725
* Common utilities for use with the OAuth providers
3826
*/
3927
class Utilities{
4028

41-
final public const ENCRYPT_FORMAT_BINARY = 0b00;
42-
final public const ENCRYPT_FORMAT_BASE64 = 0b01;
43-
final public const ENCRYPT_FORMAT_HEX = 0b10;
44-
4529
/**
4630
* Fetches a list of provider classes in the given directory
4731
*
4832
* @return array<string, array<string, string>>
4933
*/
5034
public static function getProviders(string|null $providerDir = null, string|null $namespace = null):array{
51-
$providerDir = realpath(($providerDir ?? __DIR__.'/../Providers'));
35+
$providerDir = File::realpath(($providerDir ?? __DIR__.'/../Providers'));
5236
$namespace = trim(($namespace ?? 'chillerlan\\OAuth\\Providers'), '\\');
5337
$providers = [];
5438

55-
if($providerDir === false){
56-
throw new InvalidArgumentException('invalid $providerDir');
57-
}
58-
5939
foreach(new DirectoryIterator($providerDir) as $e){
6040

6141
if($e->getExtension() !== 'php'){
@@ -79,70 +59,4 @@ public static function getProviders(string|null $providerDir = null, string|null
7959
return $providers;
8060
}
8161

82-
/**
83-
* Creates a new cryptographically secure random encryption key (in hexadecimal format)
84-
*/
85-
public static function createEncryptionKey():string{
86-
return sodium_bin2hex(sodium_crypto_secretbox_keygen());
87-
}
88-
89-
/**
90-
* encrypts the given $data with $key, $format output [binary, base64, hex]
91-
*
92-
* @see \sodium_crypto_secretbox()
93-
* @see \sodium_bin2base64()
94-
* @see \sodium_bin2hex()
95-
*/
96-
public static function encrypt(string $data, string $keyHex, int $format = self::ENCRYPT_FORMAT_HEX):string{
97-
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
98-
$box = sodium_crypto_secretbox($data, $nonce, sodium_hex2bin($keyHex));
99-
100-
$out = match($format){
101-
self::ENCRYPT_FORMAT_BINARY => $nonce.$box,
102-
self::ENCRYPT_FORMAT_BASE64 => sodium_bin2base64($nonce.$box, SODIUM_BASE64_VARIANT_ORIGINAL),
103-
self::ENCRYPT_FORMAT_HEX => sodium_bin2hex($nonce.$box),
104-
default => throw new InvalidArgumentException('invalid format'), // @codeCoverageIgnore
105-
};
106-
107-
sodium_memzero($data);
108-
sodium_memzero($keyHex);
109-
sodium_memzero($nonce);
110-
sodium_memzero($box);
111-
112-
return $out;
113-
}
114-
115-
/**
116-
* decrypts the given $encrypted data with $key from $format input [binary, base64, hex]
117-
*
118-
* @see \sodium_crypto_secretbox_open()
119-
* @see \sodium_base642bin()
120-
* @see \sodium_hex2bin()
121-
*/
122-
public static function decrypt(string $encrypted, string $keyHex, int $format = self::ENCRYPT_FORMAT_HEX):string{
123-
124-
$bin = match($format){
125-
self::ENCRYPT_FORMAT_BINARY => $encrypted,
126-
self::ENCRYPT_FORMAT_BASE64 => sodium_base642bin($encrypted, SODIUM_BASE64_VARIANT_ORIGINAL),
127-
self::ENCRYPT_FORMAT_HEX => sodium_hex2bin($encrypted),
128-
default => throw new InvalidArgumentException('invalid format'), // @codeCoverageIgnore
129-
};
130-
131-
$nonce = substr($bin, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
132-
$box = substr($bin, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
133-
$data = sodium_crypto_secretbox_open($box, $nonce, sodium_hex2bin($keyHex));
134-
135-
sodium_memzero($encrypted);
136-
sodium_memzero($keyHex);
137-
sodium_memzero($bin);
138-
sodium_memzero($nonce);
139-
sodium_memzero($box);
140-
141-
if($data === false){
142-
throw new RuntimeException('decryption failed'); // @codeCoverageIgnore
143-
}
144-
145-
return $data;
146-
}
147-
14862
}

src/OAuthOptionsTrait.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
namespace chillerlan\OAuth;
1313

1414
use chillerlan\OAuth\Storage\OAuthStorageException;
15-
use function is_dir, is_writable, max, min, preg_match, realpath, sprintf, trim;
15+
use chillerlan\Utilities\{Directory, File};
16+
use function max, min, preg_match, sprintf, trim;
1617

1718
/**
1819
* The settings for the OAuth provider
@@ -126,9 +127,9 @@ protected function set_storageEncryptionKey(string $storageEncryptionKey):void{
126127
* sets and verifies the file storage path
127128
*/
128129
protected function set_fileStoragePath(string $fileStoragePath):void{
129-
$path = realpath(trim($fileStoragePath));
130+
$path = File::realpath(trim($fileStoragePath));
130131

131-
if($path === false || !is_dir($path) || !is_writable($path)){
132+
if(!Directory::isWritable($path) || !Directory::isReadable($path)){
132133
throw new OAuthStorageException(sprintf('invalid storage path "%s"', $fileStoragePath));
133134
}
134135

0 commit comments

Comments
 (0)