Simplify and document lookup_pwned_api interface

Always return a pair from the lookup_pwned_api so that destructuring
assignment can be safely used when calling the function.  The second
argument being zero indicates the password has not been found in the
pwend database.

While at it, document the function.
This commit is contained in:
Michal Nazarewicz 2019-03-13 00:41:42 +00:00
parent f252886b95
commit 9e515019be

View File

@ -4,31 +4,40 @@ import sys
def lookup_pwned_api(pwd):
sha1pwd = hashlib.sha1(pwd.encode('ascii')).hexdigest().upper()
head = sha1pwd[:5]
tail = sha1pwd[5:]
"""Returns hash and number of times password was seen in pwned database.
Args:
pwd: password to check
Returns:
A (sha1, count) tuple where sha1 is SHA1 hash of pwd and count is number
of times the password was seen in the pwned database. count equal zero
indicates that password has not been found.
Raises:
RuntimeError: if there was an error trying to fetch data from pwned
database.
"""
sha1pwd = hashlib.sha1(pwd.encode('ascii')).hexdigest().upper()
head, tail = sha1pwd[:5], sha1pwd[5:]
url = 'https://api.pwnedpasswords.com/range/' + head
res = requests.get(url)
if res.status_code != 200:
raise RuntimeError('Error fetching "{}": {}'.format(
url, res.status_code))
hashes = (s.split(':') for s in r.text.split('\r\n'))
pred = ((head + t,count) for t,count in hashes if t == tail)
password_hit = next(pred, None)
return password_hit
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()
api_return = lookup_pwned_api(pwd)
if (api_return):
sha1pwd, count = lookup_pwned_api(pwd)
if count:
print(pwd, "was found")
print("Hash {0}, {1} occurences".format(
api_return[0], api_return[1]))
print("Hash {0}, {1} occurrences".format(sha1pwd, count))
ec = 1
else:
print(pwd, "was not found")