If you have much of an interest in security, you likely have heard of Troy Hunt’s invaluable work over at Have I been Pwned? Some years back, he started collecting credential dumps from sources like pastebin and elsewhere, and building up his own database of compromised credentials. This allows anybody to enter an email address and discovery what breaches that address appears in. Someone could then take steps as necessary to change passwords, and hopefully be cured forever from password reuse.
You can also search for the presence a password, apart from the user ID, to see if the password is likely to be used in a dictionary attack. “Ah,” you say, “but then I’m providing my password to this site, which sounds like a bad idea,” (it is). HIBP provides several layers of security to make this process safer.
First, you may provide the SHA-1 hash of the password rather than the plain text. In so doing, if HIBP doesn’t have the password, then you are only providing the hash and not the source string. But what if you don’t even want to provide the hash, since an attacker that obtains the hash will have a much easier time performing dictionary and permutation attacks on your account?
Troy thought of that. You can now elect to provide just the first five characters of the hash, and the API will return the remainder of all hashes matching the substring. You can then perform a definitive check on the client side, without revealing the full hash to the server. For instance, the SHA-1 for “password” is “5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8”. If we query the api with just the first five letters, “5baa6,” then it will return 466 matching hashes in the database, along with the number of times they appear. If you want to verify this, paste the following link into your browser
This provides any eavesdroppers almost no useful information, since there is no guarantee the password being checked appears in the list. Consider that “KEB49bet” and “HGNX1hyB” share the same first five letters in their hashes.
I wrote a couple functions in PowerShell to make it easy to call this API. The first is a simple function to return the hash of a string. Since this is a necessary part of the API call, it makes sense to make it a separate function. The second accepts a plaintext or securestring password and queries the HIBP database, returning if the password appears, and how many times.
Usage is straightforward:
Get-MDTPasswordBreachStatus -PlainTextPassword "password" -Force Index Pwned Count Hash ----- ----- ----- ---- 0 True 3303003 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
For fun, see if you can figure out how to identify more strings whose hashes collide on just the first five letters.