havibeenpwnd
https://www.youtube.com/watch?v=hhUb5iknVJs
This site has an api to check if you password has been pwnd without compromising the password itself. It has a database of breached passwords of about 550.000.000 passwords.
You just hash your password with sha1
| sha1 hash |
|---|
| echo -n "secret" | sha1sum | awk '{print S1}
e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4 -
|
The -n prevents echo from outputting a trailing newline, which would give you a different has completely. The awk command is there to remove a trailing - from the sha1sum output.
You just pass the first 5 characters of this hash and search on the api :
| test your hash |
|---|
| curl https://api.pwnedpasswords.com/range/E5E9F > dmp
|
You will get a lot of entries, but the list is now short enough to search for your hash and see if it is there.
You need to lowercase the output for searching and also keep in minds the 5 characters you provided are not included in the hashes.
And indeed you will find that secret is found 350 thousand times in breaches.
| found |
|---|
| a1ba31ecd1ae84f75caaa474f3a663f05f4:352091
|
script
The website shows an python script that does this better, i include it here fully. Simply run 'python3 pwnd.py' and test all your passwords.
| test script from computerphile |
|---|
| #!/usr/bin/env python
import hashlib
import sys
try:
import requests
except ModuleNotFoundError:
print("### pip install requests ###")
raise
def lookup_pwned_api(pwd):
sha1pwd = hashlib.sha1(pwd.encode('utf-8')).hexdigest().upper()
print(sha1pwd)
head, tail = sha1pwd[:5], sha1pwd[5:]
url = 'https://api.pwnedpasswords.com/range/' + head
res = requests.get(url)
if not res.ok:
raise RuntimeError('Error fetching "{}": {}'.format(
url, res.status_code))
hashes = (line.split(':') for line in res.text.splitlines())
count = next((int(count) for t, count in hashes if t == tail), 0)
return sha1pwd, count
def main(args):
ec = 0
for pwd in args or sys.stdin:
pwd = pwd.strip()
try:
sha1pwd, count = lookup_pwned_api(pwd)
except UnicodeError:
errormsg = sys.exc_info()[1]
print("{0} could not be checked: {1}".format(pwd, errormsg))
ec = 1
continue
if count:
foundmsg = "{0} was found with {1} occurrences (hash: {2})"
print(foundmsg.format(pwd, count, sha1pwd))
ec = 1
else:
print("{} was not found".format(pwd))
return ec
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
|