Thursday 11 June 2020

Is it safe to use " Have I been Pwned APIs ? "

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:
  1.  We take the SHA-1 message digest of  'Password@12345' .i.e 'fa39309c79ea43b63fa8e1961edd941a5002c541'.
  2.  Send the first 5 characters (uppercase) of the hash to "https://api.pwnedpasswords.com/range/{5_chars_of_hash}" and observe the response. 
  3.  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

Notes - > Git Basics , git commands

[These are my git notes related to git commands] Ref:  Git Tutorials - by Corey Schafer. ---------------------------------------------------...