From 20adb4a240c3997bd8cac7dc4dde38ab0bea0ed1 Mon Sep 17 00:00:00 2001 From: Richard Prillwitz Date: Thu, 4 Jul 2024 09:17:40 +0200 Subject: [PATCH] #94 Check for known android key hashes (#95) * #94 Check for known android key hashes instead of URL origin check in case the origin string starts with android:apk-key-hash:; * Fixed haystack needle order; --------- Co-authored-by: Richard Prillwitz --- src/WebAuthn.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/WebAuthn.php b/src/WebAuthn.php index d107c2b..2d08a69 100644 --- a/src/WebAuthn.php +++ b/src/WebAuthn.php @@ -30,6 +30,7 @@ class WebAuthn { private $_signatureCounter; private $_caFiles; private $_formats; + private $_androidKeyHashes; /** * Initialize a new WebAuthn server @@ -90,6 +91,23 @@ public function addRootCertificates($path, $certFileExtensions=null) { } } + /** + * add key hashes for android verification + * @param array $hashes + * @return void + */ + public function addAndroidKeyHashes($hashes) { + if (!\is_array($this->_androidKeyHashes)) { + $this->_androidKeyHashes = []; + } + + foreach ($hashes as $hash) { + if (is_string($hash)) { + $this->_androidKeyHashes[] = $hash; + } + } + } + /** * Returns the generated challenge to save for later validation * @return ByteBuffer @@ -603,6 +621,10 @@ public function queryFidoMetaDataService($certFolder, $deleteCerts=true) { * @throws WebAuthnException */ private function _checkOrigin($origin) { + if (str_starts_with($origin, 'android:apk-key-hash:')) { + return $this->_checkAndroidKeyHashes($origin); + } + // https://www.w3.org/TR/webauthn/#rp-id // The origin's scheme must be https @@ -619,6 +641,19 @@ private function _checkOrigin($origin) { return \preg_match('/' . \preg_quote($this->_rpId) . '$/i', $host) === 1; } + /** + * checks if the origin value contains a known android key hash + * @param string $origin + * @return boolean + */ + private function _checkAndroidKeyHashes($origin) { + $parts = explode('android:apk-key-hash:', $origin); + if (count($parts) !== 2) { + return false; + } + return in_array($parts[1], $this->_androidKeyHashes, true); + } + /** * generates a new challange * @param int $length