. */ declare(strict_types=1); namespace FireflyIII\Services\Password; use Exception; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use Log; use RuntimeException; /** * Class PwndVerifierV3 * @codeCoverageIgnore */ class PwndVerifierV3 implements Verifier { /** * Verify the given password against (some) service. * * @param string $password * * @return bool */ public function validPassword(string $password): bool { Log::debug('Now in API v3.'); $hash = strtoupper(sha1($password)); $prefix = substr($hash, 0, 5); $rest = substr($hash, 5); $uri = sprintf('https://api.pwnedpasswords.com/%s/%s', 'range', $prefix); Log::debug(sprintf('URI is %s', $uri)); $headers = [ 'User-Agent' => sprintf('Firefly III v%s', config('firefly.version')), ]; Log::debug('Headers', $headers); $opts = [ 'headers' => $headers, 'timeout' => 5, ]; Log::debug(sprintf('hash prefix is %s', $prefix)); Log::debug(sprintf('rest is %s', $rest)); try { $client = new Client; $res = $client->request('GET', $uri, $opts); } catch (GuzzleException|Exception $e) { Log::error(sprintf('Could not verify password security: %s', $e->getMessage())); return true; } Log::debug(sprintf('Status code returned is %d', $res->getStatusCode())); if (404 === $res->getStatusCode()) { return true; } $body = $res->getBody()->getContents(); try { $strpos = stripos($body, $rest); } catch (RuntimeException $e) { Log::error(sprintf('Could not get body from Pwnd result: %s', $e->getMessage())); $strpos = false; } if (false === $strpos) { Log::debug(sprintf('%s was not found in result body. Return true.', $rest)); return true; } Log::debug(sprintf('Found %s, so return FALSE.', $rest)); return false; } }