-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpwned-password.py
115 lines (86 loc) · 2.55 KB
/
pwned-password.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python3
"""Have I been Pwned password database check.
Usage: pwned-password [--help] [options] [PASSWORD]
Arguments:
PASSWORD The password to check, if empty prompt for password.
Options:
-d --debug Debug only (displays informations and quits).
-h --help Displays the help.
-v --verbose Displays more informations.
"""
import sys
import hashlib
from getpass import getpass
import requests
import docopt as docpt
from docopt import docopt
# options
options = None # type: dict
debug = False # type: bool
verbose = False # type: bool
# arguments
password = "" # type: str
def main():
"""Main method."""
# options
global debug, verbose
debug, verbose = options['--debug'], options['--verbose'] # type: bool, bool
if debug:
verbose = True
# arguments
global password
password = options['PASSWORD'] # type: str
if not password:
password = getpass('Password: ')
print()
if not password:
raise RuntimeWarning('Empty password.')
# SHA-1 hash password
password_hash = hashlib.sha1(password.encode()).hexdigest().upper()
password = ''
password_hash_prefix = password_hash[:5]
password_hash_suffix = password_hash[5:]
# API URL
url = 'https://api.pwnedpasswords.com/range/%s' % password_hash_prefix
# verbose
if verbose:
print('Password hash split: %s %s' % (password_hash_prefix, password_hash_suffix))
print('API URL %s' % url)
print()
# fetch matching hashes
r = requests.get(url)
# handle HTTP errors
if not r.ok:
print('Wrong API response, HTTP status code: %s' % r.status_code)
print(r.content)
exit(1)
pwned_hashes = {}
for pwned_hash in r.content.decode().split('\r\n'):
if debug:
print(pwned_hash)
h, n = pwned_hash.split(':')
pwned_hashes[h] = n
# look for hash suffix
pwned = pwned_hashes.get(password_hash_suffix, None)
# output
if pwned is None:
print('Password not pwned.')
else:
print('Password pwned, %s occurences.' % pwned)
print()
def cli():
"""Command-line interface"""
global options
options = docopt(__doc__)
try:
main()
except RuntimeWarning as w:
print(" Warning: %s" % w, file=sys.stderr)
sys.exit(1)
except RuntimeError as w:
print("%s" % w, file=sys.stderr)
print(docpt.printable_usage(__doc__))
sys.exit(1)
# main entry point
if __name__ == '__main__':
cli()