Search This Blog

Friday, July 24, 2020

Python - Has Your Password Been Pwned?

I was reading the Spring 2020 edition of 2600 and ran into this little article on page 18, titled "Has Your Password Been Pwned?" by Jan Markowski. It was originally written in Bash so I used it as a little exercise for Python.


#!/usr/bin/python

#
# Has Your Password Been Pwned?
# This code is based on published code published in 2600, Spring 2020, page 18
# by Jan Markowski, livetrue@pm.me
#


import getpass
import hashlib
import re
import sys
import urllib.request

def Check_PW_Pwanage(password):

    fGotAPassword = False
    try:
        PW_hash = hashlib.sha1(password)
        PW_hash_digest = PW_hash.hexdigest()
        PW_hash_digest_a = PW_hash_digest[0:5].upper()
        PW_hash_digest_b = PW_hash_digest[5:40].upper()
        fGotAPassword = True
    except:
        e = sys.exc_info()[0]
        print("Error: %s" % e)

    PW_occurances = 0

    if fGotAPassword == True:
        try:
            with urllib.request.urlopen("https://api.pwnedpasswords.com/range/%s" % PW_hash_digest_a) as response:
                sh1_res = response.read().decode()
            sh1_res_lines = sh1_res.split('\r\n')
            print("pwnedpasswords.com returned %s lines matching the beginning of your hash." % len(sh1_res_lines))
            regex = re.compile('^'+PW_hash_digest_b)
            idxs = [i for i, item in enumerate(sh1_res_lines) if re.search(regex, item)]
            sh1_res_line = sh1_res_lines[idxs[0]]
            PW_occurances = sh1_res_line[sh1_res_line.rfind(':')+1:]
        except:
            pass

    return PW_occurances
      
       
       
def main():
    password = getpass.getpass("Type your password and press enter: ")
    ret = int(Check_PW_Pwanage(password.encode()))
    if ret > 0:
        print('Your password has been pwned %s times!' % ret)
    else:
        print ('but, none of them matched your full hash.')
        print('Your Password is safe!')


if __name__ == "__main__": main()






Here is what it looks like when you run it...

This examples is using the password of '12345'.


And, when you use a password 'R\Ts)-f]'



Here's what is happening...

Putting in the password of '12345' generates the following hash...
'8CB2237D0679CA88DB6464EAC60DA96345513964'

Breaking that in to two parts get me a query part: '8CB22'
And, a search part: '37D0679CA88DB6464EAC60DA96345513964'

I get the results from https://api.pwnedpasswords.com/range/8cb22  (notice the query part at the end) and scan for the search part which points me to line 121. You should go to that page and look at the results.
'37D0679CA88DB6464EAC60DA96345513964:2389787'
From which I get the number of hits at the end as: 2389787



The front end of the pwned passwords web site is: https://haveibeenpwned.com/Passwords

If you are looking for good passwords, try the folks at Gibson Research. They have some good information on what makes a good password.

Lastly, 2600 is available at https://2600.com



Sunday, June 28, 2020

Python Gmail BCC SMPT

I was lacking personal examples for a Python SMTP sender and ran into the puzzle of BCC without listing the recipients in the header. It started with a discussion of timeouts of governing connections against a default receive connector on a Microsoft Edge Transport server, so there's a sleep in there too.

It's not perfect, but it is a good starting place....

#!/usr/bin/python

#
# gmail maximum message recipients in 24 hours: 500
#

import smtplib, getpass, time, sys

def Send_BCC_gmail(username, password, bcc):
    message_subject = "bcc only test"
    message_text = "this is \r\nonly \r\na test"

    flServerConnect = False
    try:
        SMTPServer = smtplib.SMTP_SSL('smtp.gmail.com', 465)
        SMTPServer.set_debuglevel(1)
        SMTPServer.login(username,password)
        flServerConnect = True
    except:
        e = sys.exc_info()[0]
        print("Error: %s" % e)

    if flServerConnect == True:
        try:
            for toaddr in bcc:
                message = "From: %s\r\n" % username \
                    + "To: %s\r\n" % toaddr \
                    + "Subject: %s\r\n" % message_subject \
                    + "\r\n" \
                    + message_text
                SMTPServer.sendmail(username, toaddr, message)
                time.sleep(.002)
        except:
            print("Error: %s" % sys.exc_info()[0])
            print("Error: %s" % sys.exc_info()[1])
            print("Error: %s" % sys.exc_info()[2].tb_lineno)
            print ('\r\nNot sent...   : (\r\n')
        finally:
            SMTPServer.quit()
            print ('Sent...   : )')

       
       
def main():
    username = input("Type your username and press enter: ")
    password = getpass.getpass("Type your password and press enter: ")
    bcc=[]
    bccpart = "."
    while bccpart > "" :
        bccpart = input("Additional Name. end list with an empty line by itself: ")
        if bccpart > "":
            bcc.append(bccpart)
    print(bcc)
    ## bcc = ['lesleyphillipsii@yahoo.com','lesleyphillipsii@gmail.com']
    Send_BCC_gmail(username, password, bcc)

if __name__ == "__main__": main()






When you run it it produces the following output...



And here is the important part of the header...