Skip to content

Instantly share code, notes, and snippets.

@giannitedesco
Last active December 14, 2020 09:17
Show Gist options
  • Save giannitedesco/da3752b059f0fe1b4d80a8c4465b64fd to your computer and use it in GitHub Desktop.
Save giannitedesco/da3752b059f0fe1b4d80a8c4465b64fd to your computer and use it in GitHub Desktop.
Tool to check haveibeenpwnd password database
#!/usr/bin/python
__author__ = 'Gianni Tedesco'
__url__ = 'https://github.com/giannitedesco/'
__license__ = 'Public Domain'
from hashlib import sha1
from getpass import getpass
import httpx
_prompt = 'hibp> '
def main():
def _item(rec: bytes):
h, c = rec.split(b':', maxsplit=1)
return h.decode(), int(c)
# It may seem strange to allow more than 1 persistent connection here, but
# actually there is no cost to doing this if it is never used. And it could
# be required if the service is re-implemented to use redirects in the
# future. We want the command to be responsive even on high latency links
limits = httpx.Limits(max_keepalive_connections=15, max_connections=5)
with httpx.Client(pool_limits=limits) as cl:
while True:
try:
text = getpass(_prompt)
except EOFError:
print()
return
# The API cleverly avoids users revealing to the service exactly
# which password they're looking for
sha = sha1(text.encode()).hexdigest().upper()
url = f'https://api.pwnedpasswords.com/range/{sha[:5]}'
try:
r = cl.get(url)
except BaseException as e:
print(f'{url}: {e}')
continue
# This is a bit wasteful since we keep all results
results = dict((_item(x) for x in r.read().splitlines()))
cnt = results.get(sha[5:], 0)
if cnt:
print(f'Password appears {cnt} times')
else:
print(f'Password is (probably) GOOD!')
del results
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment