Most of us may have wondered " Is it safe to use Troy Hunt's Have I Been Pawned (HIBP) API ?? "
" Is my password stored to the HIBP server ?? ",
" Is this a good idea ? ".
Short answer - Yes, No and Yes.
Interestingly your password does not even go to HIBP server.
Surprised ?? Well here goes the long answer ....
HIBP created by Troy Hunt, uses a protocol called as the k-anonymity. k-anonymity was popularized by a British scientist Junade Ali when he built a communication protocol to check if the given password has been leaked. This verification of the password uses hashing, but the password or it's corresponding hash are never disclosed.
HIBP APIs are now used by several password managers.
The HIBP Implementation:
In the HIBP API, a user is required to pass the first 5 characters of the SHA1 hash of the password to the HIBP Server. The server will then respond back with list of the last 35 characters of all the SHA-1 hashes in its database that begin with the 5 characters sent.
The user can then compare locally the remaining 35 characters of his SHA-1 digest and see if his password was ever leaked.
For example: To check if the password value 'Password@12345' is a leaked password or not:
- We take the SHA-1 message digest of 'Password@12345' .i.e 'fa39309c79ea43b63fa8e1961edd941a5002c541'.
- Send the first 5 characters (uppercase) of the hash to "https://api.pwnedpasswords.com/range/{5_chars_of_hash}" and observe the response.
- The Server will respond with a list of hash tails (last 35 characters of the hash) that match the aforementioned 5 character string along with the nos. of times they have been found in the wild.
Here is a snapshot of the curl request:
Analysis of the server response in the browser:
Below is small python script, where I am using the HIBP API (v2) to input a password value and check the inputs.
import requests
import hashlib
isStrong = True
password = input("Enter a password to check if its leaked: ")
hash_val = hashlib.sha1(password.encode('utf-8'))
hash_val_digest = hash_val.hexdigest()
hash_5chars = str(hash_val_digest[:5].upper()) # first 5 chars to be sent to HIBP Api
hash_tail = str(hash_val_digest[5:].upper()) # Convert to uppercase before sending.
response = requests.get('https://api.pwnedpasswords.com/range/' + hash_5chars) # Using HIBP Api v2
print(response.status_code) # expected 200
print("---------")
hibp_hashes = response.text.splitlines() # Stores the response as a list.
for hash_found in hibp_hashes: # Compare the values from the list locally
hash_to_compare = str(hash_found[:35]) # for each list compare the hash with the tail of our SHA-1 hash ()
if hash_to_compare == hash_tail:
count = str(hash_found[36:]) # Nos of times the password was found.
isStrong = False
print(f"Password \" {password} \" has been found {count} times in the Wild !!")
print(f"Here is its hash -> {hash_to_compare}")
break
if isStrong == True :
print("Hurray !! This password was not found in the Wild !!")
Screenshots of the output from the above script (I am printing out values on the console for a better understanding):
1. Output for a weak password:
2. Output for a strong password:
Conclusion: HIBP is an amazing resource and it has several more features. Do have a look at their site for more information https://haveibeenpwned.com.
Other Python packages you could use:
https://pypi.org/project/pyhibp/
https://pypi.org/project/haveibeenpwned/
References:
https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/
https://haveibeenpwned.com/API/v2
https://en.wikipedia.org/wiki/Have_I_Been_Pwned%3F
https://en.wikipedia.org/wiki/K-anonymity
No comments:
Post a Comment