A word about my Have I Been Pwned package

Yesterday evening I posted a Tweet about improving user entered passwords using Troy Hunt's service Have I Been Pwnd.
![]() |
A promotional tweet about my dragonbe/hibp package |


Just to give you an idea of how Have I Been Pwnd service works, I created this little diagram to visualise how I'm using the service.
![]() |
Visual representation of using HIBP service |
No passwords are sent in the clear over the internet.
No full hashes are exposed to Have I Been Pwned.
All verification happens on the server where the user enters their password.
To give you an idea how this looks in PHP code, here's a real simple example. BEWARE: this is just code used as an example! Do not copy/paste it and use it in production as it has no filtering and validation of input values!!!
<?php
header('Content-Type: application/json');
$uri = 'https://api.pwnedpasswords.com/range';
$string = $_GET['string'];
$hash = strtoupper(sha1($string, false));
$subHash = substr($hash, 0, 5);
if (3 > strlen($string)) {
echo json_encode(['hash' => $hash, 'count' => 0]);
exit(0);
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_HTTPGET => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 20,
CURLOPT_USERAGENT => 'In2qa/0.0.1-Alpha',
CURLOPT_URL => sprintf('%s/%s', $uri, $subHash),
CURLOPT_HTTPHEADER => [
'Accept' => 'application/vnd.haveibeenpwned.v2+json',
'Access-Control-Allow-Origin' => 'https://api.pwnedpasswords.com',
'Access-Control-Max-Age' => '3628800',
'Access-Control-Allow-Methods' => 'GET',
],
]);
$response = curl_exec($ch);
$response = str_replace("\r\n", PHP_EOL, $response);
$data = explode(PHP_EOL, $response);
$result = array_filter($data, function ($value) use ($hash, $subHash) {
list ($sha1, $count) = explode(':', $value);
$lookup = $subHash . $sha1;
return ($hash === $lookup);
});
if ([] === $result) {
echo json_encode(['hash' => $hash, 'count' => 0]);
exit(0);
}
$response = array_pop($result);
list ($sha1, $count) = explode(':', $response);
echo json_encode(['hash' => $hash, 'count' => $count]);
exit(0);
To facilitate the usage of this service with added filtering and validation of input values, I've created a simple Composer package: "dragonbe/hibp", which you can find on GitHub as well.
To summarise:
- No passwords are shared with HIBP
- All checks occur within your own web application
- You can do things manually, I just provided a package to make it easier
Why would you implement Have I Been Pwnd service on your web application?Not everyone who uses a computer is aware that strong passwords is a hard job and password managers are not mandatory by law or installed by default by OS vendors: don't expect everyone to apply good password hygiene.
By ensuring your users have passwords that are strong enough and not yet found in earlier breaches (see Have I Been Pwnd), you can at least ensure that if someone's user account and password are compromised, it cannot be used against your own application or service. It's not a 100% guarantee bad guys aren't exploiting your user's accounts, but at least it makes it harder to compromise based on earlier breaches.