Skip to content

Commit fbcbfe8

Browse files
authored
Bugs/fix ed25519 (#522)
Fix Ed25519 public key
1 parent 4b762e7 commit fbcbfe8

File tree

5 files changed

+45
-7
lines changed

5 files changed

+45
-7
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"ext-sodium": "*",
5555
"brick/math": "^0.9|^0.10|^0.11|^0.12",
5656
"paragonie/constant_time_encoding": "^2.6",
57+
"paragonie/sodium_compat": "^1.20",
5758
"psr/clock": "^1.0",
5859
"psr/event-dispatcher": "^1.0",
5960
"psr/http-client": "^1.0",

src/Library/KeyManagement/KeyConverter/KeyConverter.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
use InvalidArgumentException;
88
use OpenSSLCertificate;
99
use ParagonIE\ConstantTime\Base64UrlSafe;
10+
use ParagonIE\Sodium\Core\Ed25519;
1011
use RuntimeException;
1112
use SpomkyLabs\Pki\CryptoEncoding\PEM;
1213
use SpomkyLabs\Pki\CryptoTypes\Asymmetric\PrivateKey;
1314
use SpomkyLabs\Pki\CryptoTypes\Asymmetric\PublicKey;
1415
use Throwable;
1516
use function array_key_exists;
17+
use function assert;
1618
use function count;
1719
use function extension_loaded;
1820
use function in_array;
@@ -258,17 +260,31 @@ private static function tryToLoadOtherKeyTypes(string $input): array
258260
*/
259261
private static function populatePoints(PrivateKey $key, array $values): array
260262
{
261-
if (($values['crv'] === 'Ed25519' || $values['crv'] === 'X25519')) {
262-
if (! extension_loaded('sodium')) {
263-
throw new RuntimeException('Please install the Sodium extension');
264-
}
265-
$x = sodium_crypto_scalarmult_base($key->privateKeyData());
263+
$crv = $values['crv'] ?? null;
264+
assert(is_string($crv), 'Unsupported key type.');
265+
$x = self::getPublicKey($key, $crv);
266+
if ($x !== null) {
266267
$values['x'] = Base64UrlSafe::encodeUnpadded($x);
267268
}
268269

269270
return $values;
270271
}
271272

273+
private static function getPublicKey(PrivateKey $key, string $crv): ?string
274+
{
275+
switch ($crv) {
276+
case 'Ed25519':
277+
return Ed25519::publickey_from_secretkey($key->privateKeyData());
278+
case 'X25519':
279+
if (extension_loaded('sodium')) {
280+
return sodium_crypto_scalarmult_base($key->privateKeyData());
281+
}
282+
// no break
283+
default:
284+
return null;
285+
}
286+
}
287+
272288
private static function checkType(string $curve): void
273289
{
274290
$curves = ['Ed448ph', 'Ed25519ph', 'Ed448', 'Ed25519', 'X448', 'X25519'];

src/Library/Signature/Algorithm/EdDSA.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
use InvalidArgumentException;
88
use Jose\Component\Core\JWK;
99
use ParagonIE\ConstantTime\Base64UrlSafe;
10+
use ParagonIE\Sodium\Core\Ed25519;
1011
use RuntimeException;
12+
use function assert;
1113
use function extension_loaded;
1214
use function in_array;
1315
use function is_string;
@@ -40,7 +42,7 @@ public function sign(JWK $key, string $input): string
4042
throw new InvalidArgumentException('Invalid "d" parameter.');
4143
}
4244
if (! $key->has('x')) {
43-
$x = sodium_crypto_sign_publickey_from_secretkey($d);
45+
$x = self::getPublicKey($key);
4446
} else {
4547
$x = $key->get('x');
4648
}
@@ -84,6 +86,24 @@ public function name(): string
8486
return 'EdDSA';
8587
}
8688

89+
private static function getPublicKey(JWK $key): string
90+
{
91+
$d = $key->get('d');
92+
assert(is_string($d), 'Unsupported key type');
93+
94+
switch ($key->get('crv')) {
95+
case 'Ed25519':
96+
return Ed25519::publickey_from_secretkey($d);
97+
case 'X25519':
98+
if (extension_loaded('sodium')) {
99+
return sodium_crypto_scalarmult_base($d);
100+
}
101+
// no break
102+
default:
103+
throw new InvalidArgumentException('Unsupported key type');
104+
}
105+
}
106+
87107
private function checkKey(JWK $key): void
88108
{
89109
if (! in_array($key->get('kty'), $this->allowedKeyTypes(), true)) {

src/Library/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"ext-mbstring": "*",
4444
"brick/math": "^0.9|^0.10|^0.11|^0.12",
4545
"paragonie/constant_time_encoding": "^2.6",
46+
"paragonie/sodium_compat": "^1.20",
4647
"psr/clock": "^1.0",
4748
"psr/http-factory": "^1.0",
4849
"psr/http-client": "^1.0",

tests/Component/KeyManagement/JWKFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ public static function dataKeys(): iterable
297297
'kty' => 'OKP',
298298
'crv' => 'Ed25519',
299299
'd' => 'Pr9AxZivB-zSq95wLrZfYa7DQ3TUPqZTkP_0w33r3rc',
300-
'x' => 'uRhai1TsvrSB43HD-36TQ2hMQfV8ruJz7F8o0wIe1VI',
300+
'x' => 'wrI33AEj15KHHYplueUE5cnJKtbM8oVHFf6wGnw2oOE',
301301
],
302302
];
303303
yield [

0 commit comments

Comments
 (0)