Skip to content

Commit 3f8f893

Browse files
authored
Fix ed25519 public key (#519)
Fix EdDSA algorithm
1 parent 18a1fb6 commit 3f8f893

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"ext-sodium": "*",
102102
"brick/math": "^0.9|^0.10|^0.11|^0.12",
103103
"paragonie/constant_time_encoding": "^2.6",
104+
"paragonie/sodium_compat": "^1.20",
104105
"psr/clock": "^1.0",
105106
"psr/event-dispatcher": "^1.0",
106107
"psr/http-client": "^1.0",

src/Component/KeyManagement/KeyConverter/KeyConverter.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
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;
@@ -250,14 +251,29 @@ private static function tryToLoadOtherKeyTypes(string $input): array
250251
*/
251252
private static function populatePoints(PrivateKey $key, array $values): array
252253
{
253-
if (($values['crv'] === 'Ed25519' || $values['crv'] === 'X25519') && extension_loaded('sodium')) {
254-
$x = sodium_crypto_scalarmult_base($key->privateKeyData());
254+
$x = self::getPublicKey($key, $values['crv']);
255+
if ($x !== null) {
255256
$values['x'] = Base64UrlSafe::encodeUnpadded($x);
256257
}
257258

258259
return $values;
259260
}
260261

262+
private static function getPublicKey(PrivateKey $key, string $crv): ?string
263+
{
264+
switch ($crv) {
265+
case 'Ed25519':
266+
return Ed25519::publickey_from_secretkey($key->privateKeyData());
267+
case 'X25519':
268+
if (extension_loaded('sodium')) {
269+
return sodium_crypto_scalarmult_base($key->privateKeyData());
270+
}
271+
// no break
272+
default:
273+
return null;
274+
}
275+
}
276+
261277
private static function checkType(string $curve): void
262278
{
263279
$curves = ['Ed448ph', 'Ed25519ph', 'Ed448', 'Ed25519', 'X448', 'X25519'];

src/SignatureAlgorithm/EdDSA/EdDSA.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use InvalidArgumentException;
88
use Jose\Component\Core\JWK;
99
use ParagonIE\ConstantTime\Base64UrlSafe;
10+
use ParagonIE\Sodium\Core\Ed25519;
1011
use RuntimeException;
1112
use function extension_loaded;
1213
use function in_array;
@@ -40,7 +41,7 @@ public function sign(JWK $key, string $input): string
4041
throw new InvalidArgumentException('Invalid "d" parameter.');
4142
}
4243
if (! $key->has('x')) {
43-
$x = sodium_crypto_sign_publickey_from_secretkey($d);
44+
$x = $this->getPublicKey($key);
4445
} else {
4546
$x = $key->get('x');
4647
}
@@ -84,6 +85,21 @@ public function name(): string
8485
return 'EdDSA';
8586
}
8687

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

src/SignatureAlgorithm/EdDSA/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"require": {
4141
"php": ">=8.1",
4242
"ext-sodium": "*",
43+
"paragonie/sodium_compat": "^1.20",
4344
"web-token/jwt-signature": "^3.2"
4445
}
4546
}

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)