Generating a Secure Password, Saving It as a CSV, and Password Protecting a File in Python
Posted in Web Development on August 2022
Facebook Twitter PinterestI recently wrote Generating a Secure Password and Saving It to a CSV Spreadsheet in Python, which shows how to create a secure password and save it to a CSV spreadsheet. I wanted to take it a step further for those paranoid, maybe rightfully so, people who want more security on their local computer. This tutorial not only shows how to generate a secure password, save it to a CSV file, but also password protecting that file. One thing to note is that text files (including CSV) cannot be password protected. In order to achieve this, the file needs to be zipped.
Python Code
import string import secrets import csv import pyminizip import os while True: # Getting letters, numbers, and special characters characters = string.ascii_letters + string.punctuation + string.digits # Randomizing password = "".join(secrets.choice(characters) for x in range(16)) title = input("\nTitle of Password:\n>>") print("Title:\n" + title +"\n\nPassword:\n"+ password) mkfile = open("test.csv", "a", encoding="utf-8") with mkfile as file: writer = csv.writer(file) # Writes the title writer.writerow([str(title)]) # Writes the generated password writer.writerow([str(password)]) # Creates a new row writer.writerow("\n") # Repeat? y/n choice = input("\nEnter another? [y/n]") if choice == "y": continue else: mkfile.close() # Targeted file file = "test.csv" # Output of zip file output = "not-the-file-youre-looking-for.zip" # Password password = "123" # Compression level compress_lvl = 5 # Compress file pyminizip.compress(file, None, output, password, compress_lvl) # Remove the orginal file os.remove("test.csv") break
Digging Into the Code
Lines 1-5: Five modules, string, secrets, csv, pyminizip, and os are required, and I’ve linked to each of their documentation if further reading is needed. Python recommends using secrets
in lieu of the random
module noting: “In particular, secrets should be used in preference to the default pseudo-random number generator in the random module, which is designed for modelling and simulation, not security or cryptography.” Meanwhile pyminizip
is used to create a password encrypted zip file and os
to remove the original CSV.
Line 7: The entire Python code is wrapped in a while True
loop, which will run as long as the conditional expression evaluates to True. This is to allow the user to enter more generated passwords, which will be found on line 35.
Lines 10 and 13: These are variables to be used later. The characters
variable makes use of the string
module to use ascii_lowercase and ascii_uppercase constants, punctuations (e.g. !”#$%&'()*+,-./:;<=>?@[\]^_`{|}~), and digits (e.g. 0123456789). Combining these three constants will help create a strong password. To make this much more secure, the secrets
module is used to randomize the password in 16 characters.
Line 15: The title
variable is used to help the user to correlate what the password is referencing.
Line 17: In order for the user to identify their password, Python prompts “Title of Password:”. Once a title is entered, a password will be generated.
Line 19: The variable mkfile
is created to work within the object responsible for converting the user’s data into delimited strings. Firstly, it’s going to open()
a file, followed by a file name/location. Next, "a"
is used, which opens a file for appending. If the file doesn’t exist, it creates a new file for writing. I see a lot of people using "w"
, which opens a file for writing only and overwrites the file if the file exists. In this case, I don’t want to blow away my data every time I update, so I use 'a'
. Lastly, encoding="utf-8'"
makes sure the data is encoded properly.
Lines 21-32: To write to a CSV file in Python, we use the csv.writer()
function. This function writes the user’s data into a delimited string. This string can then be used to write into CSV files using the writerow()
. writer.writerow([str(title)])
and writer.writerow([str(password)])
store the variables into the CSV spreadsheet. Using str()
allows the data to be in one cell. If that was removed, each character would be on its own cell.
Lines 35-38: The user is asked whether they want to add more entries or quit. A simple if
will determine either repeating the loop or moving onto else
.
Lines 39-55: This is where the code differs from Generating a Secure Password and Saving It to a CSV Spreadsheet in Python. Firstly, mkfile.close()
will close the CSV file (e.g. test.csv). If this isn’t done, then the last generated password will be omitted. file
, output
, password
, and compress_lvl
are variables to be used for pyminizip’s compression. Here’s an example from their website: pyminizip.compress(“/srcfile/path.txt”, “file_path_prefix”, “/distfile/path.zip”, “password”, int(compress_level)). file
is targeting the file to be compressed, output
will be the name of the zip file, None
is the prefix path (string) or None (path to prepend to file), password
creates the password, and compress_lvl
compresses the file between 1 to 9 (faster to more compression).
Line 58: To make this a proper secure technique, the original file is removed.
Conclusion
I put both files, the python file that runs the code and the original CSV (test.csv), in the same folder for demonstration purposes only. This process could all be rendered worthless if the python and targeted CSV files are located in the same folder—someone could easily find your password. This can be changed within the file
variable.
I already wrote a similar tutorial, but I figured there would be someone saying that saving it to your local machine isn’t secure enough—maybe rightfully so. Regardless, I wrote this for several reasons. First, most examples of Python generated passwords aren’t making use of the string module properly (e.g. string.ascii_letters + string.punctuation + string.digits). I’ve seen a lot of people doing something like digit = “123456789” in their code–not realizing that the string module can already take care of that. Second, I’ve read debates regarding using random or secrets, but I prefer to stick with Python’s documentation and use the latter module. Third, I haven’t found examples where people give some association to their passwords. A password generator is useless, if there’s no correlation between account and password. Last, if you’re generating secure passwords, you’ll have to store that information to find later. Why not fix that and insert the data into a local file.