From d5e5ebd1ec134a521007b0d2422134aa425c4e21 Mon Sep 17 00:00:00 2001 From: Spomky Date: Mon, 11 Mar 2019 13:49:03 +0100 Subject: [PATCH] Fix EdDSA algorithm --- src/Component/Encryption/JWEDecrypter.php | 1 - src/Component/KeyManagement/JWKFactory.php | 8 +++--- src/SignatureAlgorithm/EdDSA/EdDSA.php | 9 +++---- .../EdDSA/Tests/EdDSASignatureTest.php | 25 ++++--------------- 4 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/Component/Encryption/JWEDecrypter.php b/src/Component/Encryption/JWEDecrypter.php index cef7bee9..a7c51af3 100644 --- a/src/Component/Encryption/JWEDecrypter.php +++ b/src/Component/Encryption/JWEDecrypter.php @@ -156,7 +156,6 @@ private function checkCekSize(string $cek, KeyEncryptionAlgorithm $keyEncryption return; } if (mb_strlen($cek, '8bit') !== $algorithm->getCEKSize() / 8) { - var_dump(mb_strlen($cek, '8bit'), $algorithm->getCEKSize() / 8); throw new \InvalidArgumentException('Invalid CEK size'); } } diff --git a/src/Component/KeyManagement/JWKFactory.php b/src/Component/KeyManagement/JWKFactory.php index 88819ba8..b2829e37 100644 --- a/src/Component/KeyManagement/JWKFactory.php +++ b/src/Component/KeyManagement/JWKFactory.php @@ -172,27 +172,29 @@ public static function createOKPKey(string $curve, array $values = []): JWK switch ($curve) { case 'X25519': $keyPair = \sodium_crypto_box_keypair(); - $d = \sodium_crypto_box_secretkey($keyPair); + $secret = \sodium_crypto_box_secretkey($keyPair); $x = \sodium_crypto_box_publickey($keyPair); break; case 'Ed25519': $keyPair = \sodium_crypto_sign_keypair(); - $d = \sodium_crypto_sign_secretkey($keyPair); + $secret = \sodium_crypto_sign_secretkey($keyPair); $x = \sodium_crypto_sign_publickey($keyPair); break; default: throw new \InvalidArgumentException(\sprintf('Unsupported "%s" curve', $curve)); } + $secretLength = mb_strlen($secret, '8bit'); + $d = mb_substr($secret, 0, -$secretLength / 2, '8bit'); $values = \array_merge( $values, [ 'kty' => 'OKP', 'crv' => $curve, - 'x' => Base64Url::encode($x), 'd' => Base64Url::encode($d), + 'x' => Base64Url::encode($x), ] ); diff --git a/src/SignatureAlgorithm/EdDSA/EdDSA.php b/src/SignatureAlgorithm/EdDSA/EdDSA.php index 231bfe59..8475c6a4 100644 --- a/src/SignatureAlgorithm/EdDSA/EdDSA.php +++ b/src/SignatureAlgorithm/EdDSA/EdDSA.php @@ -29,13 +29,13 @@ public function sign(JWK $key, string $input): string if (!$key->has('d')) { throw new \InvalidArgumentException('The key is not private.'); } - $secret = Base64Url::decode($key->get('d')); - $keyPair = \sodium_crypto_sign_seed_keypair($secret); - $secretKey = \sodium_crypto_sign_secretkey($keyPair); + $x = Base64Url::decode($key->get('x')); + $d = Base64Url::decode($key->get('d')); + $secret = $d.$x; switch ($key->get('crv')) { case 'Ed25519': - return \sodium_crypto_sign_detached($input, $secretKey); + return \sodium_crypto_sign_detached($input, $secret); default: throw new \InvalidArgumentException('Unsupported curve'); } @@ -46,7 +46,6 @@ public function verify(JWK $key, string $input, string $signature): bool $this->checkKey($key); $public = Base64Url::decode($key->get('x')); - switch ($key->get('crv')) { case 'Ed25519': return \sodium_crypto_sign_verify_detached($signature, $input, $public); diff --git a/src/SignatureAlgorithm/EdDSA/Tests/EdDSASignatureTest.php b/src/SignatureAlgorithm/EdDSA/Tests/EdDSASignatureTest.php index e1059ac6..ff82a68e 100644 --- a/src/SignatureAlgorithm/EdDSA/Tests/EdDSASignatureTest.php +++ b/src/SignatureAlgorithm/EdDSA/Tests/EdDSASignatureTest.php @@ -18,10 +18,8 @@ use Jose\Component\Core\Converter\StandardConverter; use Jose\Component\Core\JWK; use Jose\Component\Signature\Algorithm\EdDSA; -use Jose\Component\Signature\JWS; use Jose\Component\Signature\JWSBuilder; use Jose\Component\Signature\JWSVerifier; -use Jose\Component\Signature\Serializer\CompactSerializer; use PHPUnit\Framework\TestCase; /** @@ -31,7 +29,7 @@ class EdDSASignatureTest extends TestCase { /** - * @see https://tools.ietf.org/html/draft-ietf-jose-cfrg-curves-00#appendix-A.5 + * @see https://tools.ietf.org/html/rfc8037#appendix-A.5 * * @test */ @@ -48,13 +46,11 @@ public function edDSAVerifyAlgorithm() $input = 'eyJhbGciOiJFZERTQSJ9.RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc'; $signature = Base64Url::decode('hgyY0il_MGCjP0JzlnLWG1PPOt7-09PGcvMg3AIbQR6dWbhijcNR4ki4iylGjg5BhVsPt9g7sVvpAr_MuM0KAg'); - $result = $eddsa->verify($key, $input, $signature); - - static::assertTrue($result); + static::assertTrue($eddsa->verify($key, $input, $signature)); } /** - * @see https://tools.ietf.org/html/draft-ietf-jose-cfrg-curves-00#appendix-A.5 + * @see https://tools.ietf.org/html/rfc8037#appendix-A.5 * * @test */ @@ -68,7 +64,7 @@ public function edDSASignAndVerifyAlgorithm() ]); $header = ['alg' => 'EdDSA']; - $input = Base64Url::decode('RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc'); + $input = 'Example of Ed25519 signing'; // Corresponds to "RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc" $jwsBuilder = new JWSBuilder( new StandardConverter(), @@ -77,22 +73,11 @@ public function edDSASignAndVerifyAlgorithm() $jwsVerifier = new JWSVerifier( AlgorithmManager::create([new EdDSA()]) ); - $serializer = new CompactSerializer( - new StandardConverter() - ); $jws = $jwsBuilder ->create()->withPayload($input) ->addSignature($key, $header) ->build(); - $jws = $serializer->serialize($jws, 0); - - static::assertEquals('eyJhbGciOiJFZERTQSJ9.RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc.hgyY0il_MGCjP0JzlnLWG1PPOt7-09PGcvMg3AIbQR6dWbhijcNR4ki4iylGjg5BhVsPt9g7sVvpAr_MuM0KAg', $jws); - - $loaded = $serializer->unserialize($jws); - - static::assertInstanceOf(JWS::class, $loaded); - static::assertEquals(1, $loaded->countSignatures()); - static::assertTrue($jwsVerifier->verifyWithKey($loaded, $key, 0)); + static::assertTrue($jwsVerifier->verifyWithKey($jws, $key, 0)); } }