Skip to content

Commit ccdb0b3

Browse files
authored
Merge pull request #199 from web-token/OptLibSodium
Optional ext-sodium
2 parents 3978fa9 + b6eb82a commit ccdb0b3

File tree

9 files changed

+68
-5
lines changed

9 files changed

+68
-5
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
"ext-json": "*",
5757
"ext-mbstring": "*",
5858
"ext-openssl": "*",
59-
"ext-sodium": "*",
6059
"fgrosse/phpasn1": "^2.0",
6160
"psr/event-dispatcher": "^1.0",
6261
"psr/http-factory": "^1.0",
@@ -122,6 +121,7 @@
122121

123122
},
124123
"suggest":{
124+
"ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys",
125125
"bjeavons/zxcvbn-php": "Adds key quality check for oct keys.",
126126
"php-http/httplug": "To enable JKU/X5U support.",
127127
"php-http/httplug-bundle": "To enable JKU/X5U support.",

src/Bundle/JoseFramework/DependencyInjection/Source/Signature/SignatureSource.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,19 @@ public function getCompilerPasses(): array
124124

125125
private function getAlgorithmsFiles(): array
126126
{
127-
return [
127+
$algorithms = [
128128
RSAPSS::class => 'signature_rsa.php',
129129
ECDSA::class => 'signature_ecdsa.php',
130-
EdDSA::class => 'signature_eddsa.php',
131130
HMAC::class => 'signature_hmac.php',
132131
None::class => 'signature_none.php',
133132
HS1::class => 'signature_experimental.php',
134133
];
134+
135+
if (\extension_loaded('sodium')) {
136+
$algorithms[EdDSA::class] = 'signature_eddsa.php';
137+
}
138+
139+
return $algorithms;
135140
}
136141

137142
private function isEnabled(): bool

src/Component/KeyManagement/JWKFactory.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public static function createOctKey(int $size, array $values = []): JWK
9999
*/
100100
public static function createOKPKey(string $curve, array $values = []): JWK
101101
{
102+
self::checkSodiumIsAvailable();
102103
switch ($curve) {
103104
case 'X25519':
104105
$keyPair = sodium_crypto_box_keypair();
@@ -297,4 +298,21 @@ public static function createFromX5C(array $x5c, array $additional_values = []):
297298

298299
return new JWK($values);
299300
}
301+
302+
private static function checkSodiumIsAvailable(): void
303+
{
304+
$requiredFunctions = [
305+
'sodium_crypto_box_keypair',
306+
'sodium_crypto_box_secretkey',
307+
'sodium_crypto_box_publickey',
308+
'sodium_crypto_sign_keypair',
309+
'sodium_crypto_sign_secretkey',
310+
'sodium_crypto_sign_publickey',
311+
];
312+
foreach ($requiredFunctions as $function) {
313+
if (!\function_exists($function)) {
314+
throw new RuntimeException(sprintf('The function "%s" is not available. Have you installed the Sodium extension', $function));
315+
}
316+
}
317+
}
300318
}

src/Component/KeyManagement/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"phpunit/phpunit": "^8.0"
3333
},
3434
"suggest": {
35+
"ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys",
3536
"web-token/jwt-util-ecc": "To use EC key analyzers.",
3637
"php-http/message-factory": "To enable JKU/X5U support.",
3738
"php-http/httplug": "To enable JKU/X5U support."

src/EncryptionAlgorithm/KeyEncryption/ECDHES/ECDHES.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Jose\Component\Core\Util\Ecc\PrivateKey;
2424
use Jose\Component\Core\Util\ECKey;
2525
use Jose\Component\Encryption\Algorithm\KeyEncryption\Util\ConcatKDF;
26+
use RuntimeException;
2627

2728
final class ECDHES implements KeyAgreement
2829
{
@@ -74,6 +75,7 @@ public function calculateAgreementKey(JWK $private_key, JWK $public_key): string
7475

7576
return $this->convertDecToBin(EcDH::computeSharedKey($curve, $pub_key, $priv_key));
7677
case 'X25519':
78+
$this->checkSodiumIsAvailable();
7779
$sKey = Base64Url::decode($private_key->get('d'));
7880
$recipientPublickey = Base64Url::decode($public_key->get('x'));
7981

@@ -219,6 +221,7 @@ private function convertDecToBin(GMP $dec): string
219221
*/
220222
private function createOKPKey(string $curve): JWK
221223
{
224+
$this->checkSodiumIsAvailable();
222225
switch ($curve) {
223226
case 'X25519':
224227
$keyPair = sodium_crypto_box_keypair();
@@ -243,4 +246,22 @@ private function createOKPKey(string $curve): JWK
243246
'd' => Base64Url::encode($d),
244247
]);
245248
}
249+
250+
private function checkSodiumIsAvailable(): void
251+
{
252+
$requiredFunctions = [
253+
'sodium_crypto_scalarmult',
254+
'sodium_crypto_box_keypair',
255+
'sodium_crypto_box_secretkey',
256+
'sodium_crypto_box_publickey',
257+
'sodium_crypto_sign_keypair',
258+
'sodium_crypto_sign_secretkey',
259+
'sodium_crypto_sign_publickey',
260+
];
261+
foreach ($requiredFunctions as $function) {
262+
if (!\function_exists($function)) {
263+
throw new RuntimeException(sprintf('The function "%s" is not available. Have you installed the Sodium extension', $function));
264+
}
265+
}
266+
}
246267
}

src/EncryptionAlgorithm/KeyEncryption/ECDHES/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
"Jose\\Component\\Encryption\\Algorithm\\KeyEncryption\\": ""
2020
}
2121
},
22+
"suggest": {
23+
"ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys"
24+
},
2225
"require": {
2326
"spomky-labs/aes-key-wrap": "^5.0",
2427
"web-token/jwt-encryption": "^2.0",

src/EncryptionAlgorithm/KeyEncryption/RSA/Util/RSACrypt.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public static function encryptWithRSAOAEP(RSAKey $key, string $plaintext, string
112112
if (0 >= $length) {
113113
throw new \RuntimeException();
114114
}
115-
$plaintext = str_split($plaintext, $length);
115+
$plaintext = mb_str_split($plaintext, $length);
116116
$ciphertext = '';
117117
foreach ($plaintext as $m) {
118118
$ciphertext .= self::encryptRSAESOAEP($key, $m, $hash);
@@ -130,7 +130,7 @@ public static function decryptWithRSAOAEP(RSAKey $key, string $ciphertext, strin
130130
throw new RuntimeException();
131131
}
132132
$hash = Hash::$hash_algorithm();
133-
$ciphertext = str_split($ciphertext, $key->getModulusLength());
133+
$ciphertext = mb_str_split($ciphertext, $key->getModulusLength());
134134
$ciphertext[\count($ciphertext) - 1] = str_pad($ciphertext[\count($ciphertext) - 1], $key->getModulusLength(), \chr(0), STR_PAD_LEFT);
135135
$plaintext = '';
136136
foreach ($ciphertext as $c) {

src/SignatureAlgorithm/EdDSA/EdDSA.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,23 @@
1616
use Base64Url\Base64Url;
1717
use InvalidArgumentException;
1818
use Jose\Component\Core\JWK;
19+
use RuntimeException;
1920

2021
final class EdDSA implements SignatureAlgorithm
2122
{
23+
public function __construct()
24+
{
25+
$requiredFunctions = [
26+
'sodium_crypto_sign_detached',
27+
'sodium_crypto_sign_verify_detached',
28+
];
29+
foreach ($requiredFunctions as $function) {
30+
if (!\function_exists($function)) {
31+
throw new RuntimeException(sprintf('The function "%s" is not available. Have you installed the Sodium extension', $function));
32+
}
33+
}
34+
}
35+
2236
public function allowedKeyTypes(): array
2337
{
2438
return ['OKP'];

src/SignatureAlgorithm/EdDSA/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
}
2121
},
2222
"require": {
23+
"ext-sodium": "*",
2324
"web-token/jwt-signature": "^2.0"
2425
},
2526
"require-dev": {

0 commit comments

Comments
 (0)