Browsing Tag

Before we dive in to the topic, I would like to apologies. Over the past 10 days, I have had multiple matters that require my attention. While I try to allocate some time for everything, this blog has not been on the top of my priorities. This was a mistake, I now realize. I should have anticipated some of the issues and plan ahead accordingly. The opposite is what happened. I cannot say this will not happen again, I can only apologies and try to do better in the future. So let us get started.

The last post I wrote talked about how to password protect your python program. Although this is very neat and sufficient in most cases, what you really need is a method to authenticate users and password. This post will be rather simple and straight to the point. Much of the work it relies on we have done already. Recall at this point we are storing the password as encrypted strings in a file, independent of our python program. Now we just have 2 things we have to do. We will start by recognizing a single user and allow him/her accesses. Then, we will expand the program to allow multiple allowed users accesses. As noted before, we are going to use Python2.7, I strongly encourage referring to the documentation or download the documentation for python2.7 for offline reference.

As we did previously, before we can authenticate any user we have figure out how we want to store the data we are comparing to. You may recall we used a support program to create a file and store the password. Now we will extend the “helper” script to store a user name on a single line, followed by the encrypted password in the next line. This format may be modified at your discretion. For example, you may choose to encrypt both the user name and the password. You may also choose to have all the information as a single line, separated by a vertical line, ‘|’, or a comma, ‘,’. The options are multiple, but the principle is the same. Assuming we follow the first suggested format, here is how the code to store a user name and password will look like:


import sys
import hashlib
import getpass

def main(argv):

if len(argv) != 1:
sys.exit('Usage: store_user_pass.py <file_name>')

print '\nUser & Password Storage Program v.01\n'

if raw_input('The file ' + sys.argv[1] + ' will be erased or overwrite if exsting.\nDo you wish to continue (Y/n): ') not in ('Y','y') :
sys.exit('\nChanges were not recorded\n')

user_name = raw_input('Please Enter a User Name: ')

try:
file_conn = open(sys.argv[1],'w')
file_conn.write(user_name + '\n')
file_conn.close()
except:
sys.exit('There was a problem writing to the file!')

print '\nPassword safely stored in ' + sys.argv[1] + '\n'

if __name__ == "__main__":
main(sys.argv[1:])



Note that the changes from our previous version, store a single encrypted password, have not changed much. The main thing we have done is added a user_name variable that gets written to the file. As before, we warn the user from alteration of a file might already exist. Here is an example output of the program:

Here are the content of the file pass_db.txt:


99fb2f48c6af4761f904fc85f95eb56190e5d40b1f44ec3a9c1fa319



Now we are ready to see how the other side of this program might look like. Since we know how to verify the password, adding the user name option is not much change. For our application purpose, we will terminate the program if the user name is not known or x password attempts have been made. Here is how the code for this will look like:


import sys
import hashlib
import getpass

def main(argv):

if len(argv) != 1:
sys.exit('Usage: user_pass.py <file_name>')

print '\nUser & Password Authentication Program v.01\n'

try:
file_conn = open(sys.argv[1])
file_conn.close()
except:
sys.exit('There was a problem reading the file!')

pass_try = 0
x = 3

if raw_input('Please Enter User Name: ') != user_name:
sys.exit('Incorrect User Name, terminating... \n')

while pass_try < x:
pass_try += 1
print 'Incorrect Password, ' + str(x-pass_try) + ' more attemts left\n'
else:
pass_try = x+1

if pass_try == x and user_input != password:

print 'User is logged in!\n'

if __name__ == "__main__":
main(sys.argv[1:])



Running the code with the file we generated before, pass_db.txt:

Like previous programs, the user is prompt for a password 3 times. At each trial the user is notified the number of password attempts reaming. At this point, if you have been following along, you should be able to pice together how this might be extended to multiple users. For our final version we will have 2 python files, one to generate a password file and the other to log the user in. The modification for the storage code needed at this point are minimal, all we need to change is the mode we write to the file. In previous versions we used ‘w’ for write mode. Now we are going to use ‘a’, which is only going to append the new information to the end of the file. If the file is not yet created, the file will be created.You can look users and password storage program.

Last but not least, here is our final version of the authentication module. First the code:


import sys
import hashlib
import getpass

def process_file(file_name):

user_names = []

try:
file_conn = open(file_name)

for i in range(len(data)):
if i%2 == 0:
user_names.append(data[i][:-1])
else:

file_conn.close()
except:
sys.exit('There was a problem reading the file!')

def main(argv):

if len(argv) != 1:
sys.exit('Usage: user_pass.py <file_name>')

print '\nUser & Password Authentication Program v.01\n'

pass_try = 0
x = 3

user = raw_input('Please Enter User Name: ')

if user not in user_names:
sys.exit('Unkown User Name, terminating... \n')

while pass_try < x:
pass_try += 1
print 'Incorrect Password, ' + str(x-pass_try) + ' more attemts left\n'
else:
pass_try = x+1

if pass_try == x:

print 'User is logged in!\n'

if __name__ == "__main__":
main(sys.argv[1:])



So what is different? Now instead of just reading one user name and password, we read more. The information is stored in 2 (2things) lists that have corresponding indexes. So the user name at index 1 has an encrypted password stored at index 1 of the password list. All other operation are the same as any previous example. I do not think there is a need to include an input, it is the same as before.

For a final remark, I realize that the method I discussed in this and the previous post and this one are not very secure or useful outside of an educational exercise. In ‘real world’ applications the information will be stored in a database. There are some software that has already been pre written for user authentication in python. The bottom line is that user authentication is not enough to protect an application. There are several more methods we may or may not cover in the future. For the near time, we will start to look into security algorithms and application.

Couple weeks back we talked about how to generate passwords in python. Now, I would like to explore how to password protect your application. We will be using Python again, only this time I will upgrade to Python2.7 due to popular demand. You can reference to Python2.7 the documentation or download Python2.7 documentation.

There are many situations in which you would like to password protect the application. It could be just a simple application you do not want anyone else to run, or it could be an application that stores sensitive data. The two things you need to keep in mind is that authentication is independent of the application and that we are discussing application authentication. That is, the ideas may apply to web, mobile & other applications, however, we are going to limit this discussion to python application.

Let us start by assuming there is an application we wish to secure. For demonstration purpose, the application will simply print out:

User is logged in!

Otherwise an appropriate error message will be displayed. We can agree that the print statement can be replaced with a function call to start an application. We are going to start with the simplest case. We have a string password that is stored in a variable. We prompt the user for a password. If the user input does not match the stored password, we terminate the application without letting the user log in. Here is what that would look like in code:


import sys

def main():

print 'User is logged in!\n'

if __name__ == &quot;__main__&quot;:
main()



And the output of the program in both cases:

You can see that the first time the user entered ‘password’ for the password. The program recognizes an incorrect password and is terminated. The second time the user entered the correct password ‘abcd’ and the user was successfully logged in. For a simple application, this might be enough. However, we are going to take this idea much further. To start, let us add the ability for the user to try to enter a password x amount of times before the program is terminated. For now, let us assume x is 3. You might change the value of x to any number you wish. Our modifed program might look like this:


import sys

def main():

pass_try = 0
x = 3

while pass_try &lt; x:
pass_try += 1
print 'Incorrect Password, ' + str(x-pass_try) + ' more attempts left\n'
else:
pass_try = x + 1

if pass_try == x and user_input != password:

print 'User is logged in!\n'

if __name__ == &quot;__main__&quot;:
main()



Sample output:

If you examine the code you might notice a few different things. We have a while-loop that runs for x amount of times. This might be replaced with a simple for-loop, but keep in mind that there is no guarantee that the user will need any incorrect attempts. In addition, if you do use a for loop, you might need to use a break statement, which is not a good programming habit. You might also notice that that the program notifies the user how many attempts he or she has left. This is not required, but as a user it is nice to know.

As you examine the code, you will soon realize that storing the password in the code as a string is not the best practice. Let us move the password into a file. This way we can separate the password from the program. The path for the file will be given as a command line argument. The file can by anywhere in the file system, including on a USB drive. Without it, the program will not run and terminate immediately. For this example, we will store the password in a plain txt file called pass_file1.txt. Here is the content of the text file:


abcd



Here is our new version, using the file to store the password:


import sys

def main(argv):

if len(argv) != 1:
sys.exit('Usage: pass_auth3.py &lt;file_name&gt;')

try:
file_conn = open(sys.argv[1])
file_conn.close()
except:
sys.exit('There was a problem reading the file!')

pass_try = 0
x = 3

while pass_try &lt; x:
pass_try += 1
print 'Incorrect Password, ' + str(x-pass_try) + ' more attempts left\n'
else:
pass_try = 4

if pass_try == x and user_input != password:

print 'User is logged in!\n'

if __name__ == &quot;__main__&quot;:
main(sys.argv[1:])



And here is some sample output. Notice that the first try is without giving the program a path to a file.

Take a closer look at the code. You will notice that there is more than one way the program can might terminate. If a file is not provided the program will terminate immediately. If there are any issues reading the file the program will terminate. Finally, if the password is incorrect more than x times the program will terminate. When reading from the file we use the readline() method. This will read an entire line from the file, including the newline character ‘\n’. This is why there is an added [:-1] to trim the string to not include the newline character.

So far we have seen how to ask for a simple password. However, this is far from a real-world application strength. The problem is that the password is stored as a plain text file. This means that if anyone was to open it, they will know your password immediately. As a good programmer, you do not want a client to find out their secure passwords are stored in plain text. Much less a user finding that out. Or worse. To solve this problem we will introduce 2 (2things) new ideas. First a method to avoid seeing the characters as the user types. Second, we will encrypt the password we store in the file using one way encryption.

In order to hide the password while the user is typing, we will use a python standard library named getpass. The library is quite small, but provides exactly what the name suggests and nothing else. Here is a simple example of how the library works:

Basically, getpass.getpass() is equivalent to using raw_input(), but hides the typed characters. I think it is rather straight forward why you should use this library when asking a user for a password. Moving on to the second thing, we need a way to encrypt our password. Furthermore, we want our password encrypted using a one way encryption method. This means that once we encrypt the data, there is no simple function to retrieve the data. Python has a multiple ways to achieve this using standard library functions. We will use a built-in library called hashlib that provides many encryption methods. I choose to follow on of the examples and use sha224 with conversion to hex. Here is an example of using sha224:

You can see that the encrypted string has nothing to do with the string ‘password’. So how are we going to use one way encryption? Simple, we are going to store the original encrypted password in the file. Then when the user enters a password we will encrypt the user input exactly the same way and compare the encrypted string from the file. If we do not use the same encryption algorithm, this method will not work. You may change the encryption algorithm to what every method you like. Since we need to encrypt the passwords, we will need a helper program to store the password before we modify the authentication program. Here is an example program to store the an encrypted password:


import sys
import hashlib
import getpass

def main(argv):

if len(argv) != 1:
sys.exit('Usage: store_pass.py &lt;file_name&gt;')

if raw_input('The file ' + sys.argv[1] + ' will be erased or overwrite if existing.\nDo you wish to continue (Y/n): ') != 'Y' :
sys.exit('\nChanges were not recorded\n')

try:
file_conn = open(sys.argv[1],'w')
file_conn.close()
except:
sys.exit('There was a problem writing to the file!')

print '\nPassword safely stored in ' + sys.argv[1] + '\n'

if __name__ == &quot;__main__&quot;:
main(sys.argv[1:])



Here is an example output for this program:

The program is fairly simple. First we verify that the user acknowledges that if the file exists already it will be erased. There are other ways around this, but this is one of the simple solutions. You do not want to assume the user entered the right file name the first time. If you were to use a file name that already exists, the file will be permanently altered. Since we opened the file in write mode, we will erase any information already there. This is why you should double check that the user entered the correct file name. Of course, you do not have to do it and you may erase the associated if statement.

As a last note, we do not store the plain value of the password in a variable. Instead it is transferred directly to the encryption method. This offers some extra security to you program. Finally, we write the information to the file and terminate the program. If we were to look at the content of pass_file2.txt we will see something like this:


a76654d8e3550e9a2d67a0eeb6c67b220e5885eddd3fde135806e601



Now we are ready for our final version of password authentication, using the encrypted password file. Here is the code for it:


import sys
import hashlib
import getpass

def main(argv):

if len(argv) != 1:
sys.exit('Usage: pass_auth3.py &lt;file_name&gt;')

try:
file_conn = open(sys.argv[1])
file_conn.close()
except:
sys.exit('There was a problem reading the file!')

pass_try = 0
x = 3

while pass_try &lt; x:
pass_try += 1
print 'Incorrect Password, ' + str(x-pass_try) + ' more attempts left\n'
else:
pass_try = 4

if pass_try == x and user_input != password:

print 'User is logged in!\n'

if __name__ == &quot;__main__&quot;:
main(sys.argv[1:])



Notice that not much has changed. What we have added is applying the same encryption method we did to the file, to the user input. Here is how the program looks like when it runs:

We have explored adding a password security to your python program. If you really want to use it, you will need to conceal your code. One way to conceal your code is to compile code to a pyc file. This is just one way you might do this. There are other methods you could explore to create executable from p a py file. We will not explore them within this post. For the moment, I will leave you with a pyc file and a file containing an encrypted password. The application will have a unique output. Can you make the application run?

The answer to this question is short and simple, we do what we can. In this post we will look at how to randomly generate passwords and how to check their security level to some degree. So let us get to it. Generating passwords is something that is rather straight forward. To sum it all up, randomly choose X characters from a given set. We will look at a few ways to generate passwords starting from a simple one. All of them follow that same basic rule.


import random
import sys

def main(argv):

if (len(sys.argv) != 2):

for i in range(int(argv[0])):

if __name__ == "__main__":
main(sys.argv[1:])



Using the python random module and passing in via command line the length of the password, we are able to randomly generate a unique password. The passwords are built from all printable ASCII characters randomly chosen. Later we will come back to this example to test a checking password strength program. Here are some example runs of this program.

This is a nice and simple script anyone can write and by all means use and distribute. It might be a quick hack, but still is not enough to get to be a true generator. Before we move on to another, more sophisticated password generator, lets actually look at a really unique generator using python's lambda.


import random
import string

pass_gen = lambda length, ascii =  string.ascii_letters + string.digits + string.punctuation: "".join([list(set(ascii))[random.randint(0,len(list(set(ascii)))-1)] for i in range(length)])



To use this lambda simply call it with the length required, like so:

Most password requirements today specify the number of special characters, uppercase, lowercase and numbers require in a password. Using the python string library, we can use string attributes to choose a number of specific characters from each set. Now we can modify our password generator to accept the number of uppercase, lowercase, digits and special charcters. The new code and example output will look like this:


import random
import sys
import string

def main(argv):

if (len(sys.argv) != 5):
sys.exit('Usage: simple_pass.py <upper_case> <lower_case> <digit> <special_characters>')

for i in range(len(argv)):
for j in range(int(argv[i])):
if i == 0:
elif i == 1:
elif i == 2:
elif i == 3:

if __name__ == "__main__":
main(sys.argv[1:])



So at this point we can generate randomize and customize passwords. Let us now move to checking a password strength algorithm and check what kind of passwords we are generating. We will start by using a modified version of a password checker found on Password Advisor. I had to modify the code to get it to run and to create some output. Take a look.


import re

strength = ['Blank','Very Weak','Weak','Medium','Strong','Very Strong']
score = 1

return strength[0]
return strength[1]

score = score + 1
score = score + 1

score = score + 1
score = score + 1
score = score + 1

return strength[score]

def main():

user_input = raw_input("Check: ")

while(user_input != 'quit'):
user_input = raw_input("Check: ")

if __name__ == "__main__":
main()



The program uses length and python's regular expressions to determine a score for the password. This is a fairly straight forward calculation. A password longer than 8 characters is awarded 1 point, longer than 10 is awarded an additional point. Then, for each character from a character set the password is awarded another point. The points corresponding to an index on the strength list and an appropriate rating is determined. Let us see how our three password generators from before hold up to this checker standards. (The code has been slightly modified for testing).


import random
import string
import re
import sys

def ex1(num):

for i in range(int(num)):

ex2 = lambda length, ascii =  string.ascii_letters + string.digits + string.punctuation: "".join([list(set(ascii))[random.randint(0,len(list(set(ascii)))-1)] for i in range(length)])

def ex3(argv):

for i in range(len(argv)):
for j in range(int(argv[i])):
if i == 0:
elif i == 1:
elif i == 2:
elif i == 3:

def checker(argv):

example_1 = ex1(argv[1])

example_2 = ex2(int(argv[2]))

example_3 = ex3([argv[3],argv[4],argv[5],argv[6]])

def main(argv):
if (len(sys.argv) != 7):
sys.exit('Usage: ex4.py <length1> <length2> <upper_case> <lower_case> <digit> <special_characters>')

checker(sys.argv)

if __name__ == "__main__":
main(sys.argv[1:])



Let us look at least at one more measure of password strength called bit strength, used to measure the strength of random generated passwords. it follows a formula where each character contributes an amount of bits calculated by the following formula:

The results is multiplied by the number of characters and a final bit strength is calculated. The threshold recommend, according to Wikipedia, for most secure systems is 80-bits. Let us look at how this will look in code and how our generated passwords measure up to this threshold. The code is very similar to the previous example, only replacing the checker function. (Download code for password generator and checker)