This commit is contained in:
koksnuss 2019-07-10 23:45:39 +02:00
parent b1fb5f34cc
commit bfb35b2517
2 changed files with 52 additions and 73 deletions

0
build.sh Normal file → Executable file
View File

123
src/have_I_b33n_pwned.py Normal file → Executable file
View File

@ -27,80 +27,65 @@
from os import name from os import name
from sys import argv, stdout, exit from sys import argv, stdout, exit
from re import match
from argparse import ArgumentParser from argparse import ArgumentParser
from hashlib import sha1 from hashlib import sha1
from getpass import getpass from getpass import getpass
from requests import get from requests import get
if name == 'nt': if name == 'nt': # disable colors for windows environment
(RED, GREEN, RESET) = ("", "", "") (RED, GREEN, RESET) = ("", "", "")
else: else:
RED = "\033[1;31m" (RED, GREEN, RESET) = ("\033[1;31m", "\033[0;32m", "\033[0;0m")
GREEN = "\033[0;32m"
RESET = "\033[0;0m" PASSWORD_API = 'https://api.pwnedpasswords.com/range/'
API = 'https://api.pwnedpasswords.com/range/' MAIL_API = 'https://haveibeenpwned.com/api/v2/breachedaccount/'
API_MAIL = 'https://haveibeenpwned.com/api/v2/breachedaccount/'
ROW = '{:<30}{:<10}{:<45}' ROW = '{:<30}{:<10}{:<45}'
HIDDEN = False HIDDEN = True
INFINITE = True
parser = ArgumentParser( parser = ArgumentParser(
description='Check if your email or password appears in a data leak.', description='Check if your email or password appears in a data leak.',
epilog='Moritz Münch, moritzmuench@mailbox.org, willipink.eu, GPL3+' epilog='Moritz Münch, moritzmuench@mailbox.org, willipink.eu, GPL3+')
) parser.add_argument('input',
parser.add_argument('-m', '-mail', '--mail', nargs='*',
metavar='foo@adress.bar', metavar='password or mail adress',
nargs='+', help='''You can specify passwords and mail adresses seperated by spaces.
help='Email address which should be checked against the leak database.' If the password contains a space you have to enclose it in quotes like ' or
) "''')
parser.add_argument('-p', '-password', '--password', parser.add_argument('-s', '-show', '--show',
metavar='password', nargs='?',
nargs='+', help='Show entered in leak summary')
help='Password which should be checked against the leak database.'
)
args = parser.parse_args() args = parser.parse_args()
if args.show:
HIDDEN = False
def input_prompt():
def header():
print()
print(ROW.format('password', 'leaked', 'sha1'))
print('-' * 80)
def prompt_password_or_mail():
print()
while True:
choice = input('Do you wannt to check a password [p] or an email adress [e]: ')
if choice == 'p':
prompt_password()
elif choice == 'e':
prompt_mail()
def prompt_password():
print()
password = getpass('Tell me your password: ')
global HIDDEN global HIDDEN
HIDDEN = True if HIDDEN:
header() user_input = getpass('Tell me your password or mail adress: ')
query_password(password) else:
user_input = input('Tell me your password or mail adress: ')
check_mail_or_password(user_input)
def prompt_mail(): def check_mail_or_password(user_input):
print() valid_mail = match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', user_input)
mail = input('Tell me your mail adress: ') if valid_mail:
global HIDDEN query_mail(valid_mail.group())
HIDDEN = True else:
header() query_password(user_input)
query_mail(mail)
def query_password(password): def query_password(password):
''' Query the first 5 digits of the sha1 hash of the user input
ti the haveibeenpwned.com api. '''
password_hash = sha1(password.encode('UTF-8')).hexdigest().upper() password_hash = sha1(password.encode('UTF-8')).hexdigest().upper()
request = password_hash[:5] request = password_hash[:5]
response = get(API + request).text response = get(PASSWORD_API + request).text
hash_searched = 'not yet' hash_searched = 'not yet'
for answer in response.splitlines(): for answer in response.splitlines():
data = answer.split(':') data = answer.split(':')
@ -108,26 +93,23 @@ def query_password(password):
if password_hash == combined_hash: if password_hash == combined_hash:
hash_searched = int(data[1]) hash_searched = int(data[1])
break break
if hash_searched == 'not yet': if hash_searched == 'not yet':
stdout.write(GREEN) stdout.write(GREEN)
else: else:
stdout.write(RED) stdout.write(RED)
if HIDDEN: if HIDDEN:
password = '*' * len(password) password = '*' * len(password)
print(ROW.format('password', 'leaked', 'sha1'))
print('-' * 80)
print(ROW.format(password, hash_searched, password_hash)) print(ROW.format(password, hash_searched, password_hash))
stdout.write(RESET) stdout.write(RESET)
if INFINITE:
if HIDDEN: input_prompt()
prompt_password_or_mail()
def query_mail(mail): def query_mail(mail):
print()
try: try:
response = get(API_MAIL + mail).json() response = get(MAIL_API + mail).json()
for breach in response: for breach in response:
print('Name: {}'.format(breach['Name'])) print('Name: {}'.format(breach['Name']))
print('Title: {}'.format(breach['Title'])) print('Title: {}'.format(breach['Title']))
@ -137,28 +119,25 @@ def query_mail(mail):
print('Modified date: {}'.format(breach['ModifiedDate'])) print('Modified date: {}'.format(breach['ModifiedDate']))
print('Pwn count: {}'.format(breach['PwnCount'])) print('Pwn count: {}'.format(breach['PwnCount']))
print('Description: {}'.format(breach['Description'])) print('Description: {}'.format(breach['Description']))
stdout.write(RED)
print('Breached data: {}'.format(', '.join([data for data in breach['DataClasses']]))) print('Breached data: {}'.format(', '.join([data for data in breach['DataClasses']])))
stdout.write(RESET)
print('Verified: {}'.format('yes' if breach['IsVerified'] == 1 else 'No')) print('Verified: {}'.format('yes' if breach['IsVerified'] == 1 else 'No'))
print('Fabricated: {}'.format('yes' if breach['IsFabricated'] == 1 else 'No')) print('Fabricated: {}'.format('yes' if breach['IsFabricated'] == 1 else 'No'))
print('Sensitive: {}'.format('yes' if breach['IsSensitive'] == 1 else 'No')) print('Sensitive: {}'.format('yes' if breach['IsSensitive'] == 1 else 'No'))
print('Retired: {}'.format('yes' if breach['IsRetired'] == 1 else 'No')) print('Retired: {}'.format('yes' if breach['IsRetired'] == 1 else 'No'))
print('Spam: {}'.format('yes' if breach['IsSpamList'] == 1 else 'No')) print('Spam: {}'.format('yes' if breach['IsSpamList'] == 1 else 'No'))
except: except:
print('The mail adress {} was not found in any leak databases so far'.format(mail)) stdout.write(GREEN)
print('The mail adress {} is not in the leak database.'.format(mail))
if HIDDEN: stdout.write(RESET)
prompt_password_or_mail() query_password(mail)
if __name__ == '__main__': if __name__ == '__main__':
if args.password: if args.input:
header() for user_input in args.input:
for password in args.password: check_mail_or_password(user_input)
query_password(password)
elif args.mail:
for mail in args.mail:
query_mail(mail)
else: else:
prompt_password_or_mail() INFINITE = True
print() input_prompt()
exit(0)