From cd4b66baf981b9707956f0878c3aa5da9caaa9f8 Mon Sep 17 00:00:00 2001 From: Henrik Alves <89079890+henrikalves@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:00:08 +0200 Subject: [PATCH 1/3] openssl ed25519 fix --- src/WebAuthn.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/WebAuthn.php b/src/WebAuthn.php index f2eb755..c9ecaa1 100644 --- a/src/WebAuthn.php +++ b/src/WebAuthn.php @@ -186,7 +186,7 @@ public function getCreateArgs($userId, $userName, $userDisplayName, $timeout=20, // supported algorithms $args->publicKey->pubKeyCredParams = []; - if (function_exists('sodium_crypto_sign_verify_detached') || \in_array('ed25519', \openssl_get_curve_names(), true)) { + if (function_exists('sodium_crypto_sign_verify_detached') || defined('OPENSSL_KEYTYPE_ED25519')) { $tmp = new \stdClass(); $tmp->type = 'public-key'; $tmp->alg = -8; // EdDSA @@ -677,7 +677,7 @@ private function _createChallenge($length = 32) { private function _verifySignature($dataToVerify, $signature, $credentialPublicKey) { // Use Sodium to verify EdDSA 25519 as its not yet supported by openssl - if (\function_exists('sodium_crypto_sign_verify_detached') && !\in_array('ed25519', \openssl_get_curve_names(), true)) { + if (\function_exists('sodium_crypto_sign_verify_detached') && !defined('OPENSSL_KEYTYPE_ED25519')) { $pkParts = []; if (\preg_match('/BEGIN PUBLIC KEY\-+(?:\s|\n|\r)+([^\-]+)(?:\s|\n|\r)*\-+END PUBLIC KEY/i', $credentialPublicKey, $pkParts)) { $rawPk = \base64_decode($pkParts[1]); @@ -685,7 +685,7 @@ private function _verifySignature($dataToVerify, $signature, $credentialPublicKe // 30 = der sequence // 2a = length 42 byte // 30 = der sequence - // 05 = lenght 5 byte + // 05 = length 5 byte // 06 = der OID // 03 = OID length 3 byte // 2b 65 70 = OID 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm) @@ -709,6 +709,17 @@ private function _verifySignature($dataToVerify, $signature, $credentialPublicKe throw new WebAuthnException('public key invalid', WebAuthnException::INVALID_PUBLIC_KEY); } - return \openssl_verify($dataToVerify, $signature, $publicKey, OPENSSL_ALGO_SHA256) === 1; + $algo = OPENSSL_ALGO_SHA256; + + if(defined('OPENSSL_KEYTYPE_ED25519')) { + $publicKeyDetails = openssl_pkey_get_details($publicKey); + + if($publicKeyDetails && $publicKeyDetails['type'] === OPENSSL_KEYTYPE_ED25519) { + // algorithm 0 is used because EdDSA has a built-in hash + $algo = 0; + } + } + + return \openssl_verify($dataToVerify, $signature, $publicKey, $algo) === 1; } } From e59481e59f76a61821e14bb38bdf57545195b370 Mon Sep 17 00:00:00 2001 From: Henrik Alves <89079890+henrikalves@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:12:23 +0200 Subject: [PATCH 2/3] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43ea980..36281fe 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ Availability of built-in passkeys that automatically synchronize to all of a use ## Requirements * PHP >= 8.0 with [OpenSSL](http://php.net/manual/en/book.openssl.php) and [Multibyte String](https://www.php.net/manual/en/book.mbstring.php) * Browser with [WebAuthn support](https://caniuse.com/webauthn) (Firefox 60+, Chrome 67+, Edge 18+, Safari 13+) -* PHP [Sodium](https://www.php.net/manual/en/book.sodium.php) (or [Sodium Compat](https://github.com/paragonie/sodium_compat) ) for [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) support +* PHP [Sodium](https://www.php.net/manual/en/book.sodium.php) (or [Sodium Compat](https://github.com/paragonie/sodium_compat)) for [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) support, or OpenSSL (PHP ≥ 8.4) with native Ed25519 support ## Infos about WebAuthn * [Wikipedia](https://en.wikipedia.org/wiki/WebAuthn) From dcb8493f736dfa69801b94eb8dd28473d4ad0e3c Mon Sep 17 00:00:00 2001 From: Henrik Alves <89079890+henrikalves@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:19:39 +0200 Subject: [PATCH 3/3] update comment --- src/WebAuthn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebAuthn.php b/src/WebAuthn.php index c9ecaa1..a8c6961 100644 --- a/src/WebAuthn.php +++ b/src/WebAuthn.php @@ -676,7 +676,7 @@ private function _createChallenge($length = 32) { */ private function _verifySignature($dataToVerify, $signature, $credentialPublicKey) { - // Use Sodium to verify EdDSA 25519 as its not yet supported by openssl + // Use Sodium to verify EdDSA 25519 if it's not supported by openssl if (\function_exists('sodium_crypto_sign_verify_detached') && !defined('OPENSSL_KEYTYPE_ED25519')) { $pkParts = []; if (\preg_match('/BEGIN PUBLIC KEY\-+(?:\s|\n|\r)+([^\-]+)(?:\s|\n|\r)*\-+END PUBLIC KEY/i', $credentialPublicKey, $pkParts)) {