Save passwords to JSON file with encryption using python

Chitti Naidu
6 min readAug 25, 2020

--

Project Overview:

Here we’ll write a python program to save our passwords encrypted with a key into a JSON file.

Objectives:

  1. Encrypting plain text using Cryptography package (“pip install cryptography”).
  2. Save text into a JSON file using Json package (“pip install json”).

Summary:

It is hard to remember all the passwords we use daily either for work or for some social media accounts. We have some many applications out there to do this job. But we have a doubt on our privacy. So, we can save our passwords to a file. Still our passwords can be accessed by anyone who have access to that file. So, to encrypt the plain text and save it in a file we use python.

Encrypted password with account name and ID

Program explanation:

So, getting started, first python should be installed on our system (To check for python already installed or not enter “python” for python2 or “python3” for python3 in command prompt). Next, we need to install required packages for this program.

  1. Cryptography package (pip install cryptography)
  2. Json package(pip install json)

To encrypt plain text:

from cryptography.fernet import Fernet 
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2
import PBKDF2HMAC
import base64

We import these packages to use our own password as the key to encrypt and decrypt the text.

Here we use Symmetric encryption (encryption when key used to encrypt and decrypt the text is same). To use symmetric encryption, we create instance of Fernet class which is implementation of AES(Advanced Encryption Standard).

We also import base64 so that our key will have a url safe encoded key.

Password as key:

key = input("Enter the key: ").encode()
salt = b'SALT'
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
_key = base64.urlsafe_b64encode(kdf.derive(key))

The above lines of code are used to convert a user defined password to a Fernet key.

Encrypt and decrypt message: To encrypt and decrypt we need a message and a key. We produced a key above from our own password and the message has to be in bytes format. We can convert a string to bytes using encode() method.

message = "Hello world".encode()
f = Fernet(key)
encrypted = f.encrypt(message)
decrypted = f.decrypt(encrypted)

Here message is converted from string to bytes and we created an instance for class Fernet as f passing key as argument.

encrypt() and decrypt() methods are used to encrypt and decrypt string respectively. While decrypting an encrypted text we should the same key that we used to encrypt else cryptography.fernet.InvalidToken will be raised.

Saving text to JSON file: We have encrypted our passwords and need to save to a file to use whenever wanted. So, we use .json formatted file to save our passwords. JSON file stores as key-value pair similar to dictionary in python, so that we can access the passwords easily using account name or ID. We need to import json package which comes inbuilt when python installed else we can install using command pip install json.

import json

Sometimes we have multiple accounts in a single website or application. So, we need to save account name, ID and the password associated with it.

To do this, we create three functions to read and write to json file.

  1. _read(): This function reads the data from json file and stores it in an object (obj).
  2. _write(): This function writes the data to json file.
  3. __ init__(): This function helps to create a empty json file to avoid errors while reading the contents.

_read():

def _read(account,ID):
try:
fp = open("passwords.json","r")
obj = json.load(fp)
except:
__init__()
fp = open("passwords.json","r")
obj = json.load(fp)
finally:
fp.close()
return obj.get(account).get(ID)

As we discussed previously, json file consists data in terms of key-value pair which is dictionary in python. Object (obj) is a dictionary which contains the contents of json file. In the dictionary obj, let us consider having two different accounts for the same application with two different IDs. So, we create another dictionary within obj with account name as key. Inside this dictionary we have ID as key and password as value.

So, to get a particular password we need account name and ID. We pass them as arguments to our read function. Inside the function we use try and except blocks to handle errors occurred while reading file.

Finally, obj.get(account).get(ID) in this line, obj.get(account) returns the dictionary of that particular account and get(ID) returns password associated with that ID.

_write():

def _write(account,ID,Pass):
try:
fp = open("passwords.json","r")
obj = json.load(fp)
except:
__init__()
fp = open("passwords.json","r")
obj = json.load(fp)
finally:
fp.close()
try:
fp = open("passwords.json","w")
if account not in obj.keys():
obj[account] = {ID:Pass}
elif account in obj.keys():
if ID not in obj[account]:
obj[account][ID] = Pass
print("Password added.")
print(f"{account}\n{ID}:{password}")
elif ID in obj[account]:
print("Password found.")
print("Changing password...")
print("Old passsword is: ",obj[account][ID])
obj[account][ID] = Pass
print("Password changed.")

fp.write(json.dumps(obj,indent = 4))
finally:
fp.close()

After encrypting the password, we write it to json file. Similar to read function, inside write function we first handle with errors raised during runtime due to file operations and the we begin to write contents.

So first, we read all the contents from the file and save them to an object obj(dictionary). Then we append the password accordingly. First we check whether the account is already present in the file or not, if not we directly insert the ID and password as dictionary with key as account name. Else we check whether the ID is present or not inside the dictionary for that account name. If already there we change password to new by printing “password changed.” Else we create an entity with key as ID and value as password.

Finally we save the object to the file again in the line fp.write(json.dumps(obj, indent = 4)) (indent parameter is used to represent indentation inside the json file.)

__init__() :

def __init__():try:
fp = open("passwords.json","w")
data = {}
fp.write(json.dumps(data,indent=4))
finally:
fp.close()

It is just a simple function to create an empty json file if we get error while reading the file.

mode = input("Enter mode['encrypt','e','decrypt','d','change','c']: ").lower()
if mode[0] in ['e','c']:
account = input("Enter the account name: ")
ID = input("Enter account ID: ")
password = input("Enter the {}password: ".format('' if mode[0] == 'e' else 'new ')).encode()
elif mode[0] == 'd':
account = input("Enter the required account name: ")
ID = input("Enter ID: ")
else:
print("Mode unidentified.")

Getting started with main program, first we read the account name, ID and password according to the mode we need.

key = input("Enter the key: ").encode()
salt = b'SALT'
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
_key = base64.urlsafe_b64encode(kdf.derive(key))
f = Fernet(_key)if mode[0] in ['e','c']:
Pass = f.encrypt(password)
print(f"Encrypted.\n{account}\n{ID}: {Pass}")
_write(account,ID,Pass.decode())
elif mode[0] == 'd':
try:
password = _read(account,ID)
if password is None:
print("Password not found.")
continue
Pass = f.decrypt(password.encode())
print(f"Decrypted.\n{account}\n{ID}: {Pass.decode()}")
except AttributeError:
print("Can't find account.")
except:
print("Sorry! key didn't match.\nEnter correct key.")

Then we create Fernet key from password, create an instance of Fernet class, and if the mode is to encrypt or change password we encrypt with .encrypt() method and call write function by passing account name, ID and the encrypted password. And if mode is to decrypt we call read function passing account name and ID and pass the returned value to .decrypt() method and then print it.

Conclusion:

Congratulations, we have written a python program to encrypt our passwords and save them to a json formatted file.

Sorry if any mistakes or errors.

Feel free to suggest and give feedback in the comments.

Thank you for reading.

Links and references:

You can find the full code here.

Read more about encryption with cryptography package.

Learn more about working with json files.

Learn more about python dictionaries.

Originally published at http://github.com.

--

--