Password management is one of the most critical activities for being secure online. But with several dozen (if not hundreds) of accounts, how do you remember difficult, new passwords for every website? That's where a password manager is useful.

Though there are plenty of excellent password managers available (such as Bitwarden, LastPass, and 1Password), creating your own is a fun and instructive cybersecurity project. In this blog post, we'll show you how to create a basic, secure password manager from scratch.

Whether you're a cybersecurity student, enthusiast, or just curious about how things work, this tutorial will explain the key concepts at play.

Prefer watching instead of reading? Here’s a quick video guide

https://youtu.be/Q1si8Ro0HxY?embedable=true

What Is a Password Manager?

A password manager is a utility that:

When you create one, you want security + usability. You should:

Select Your Tech Stack

For this project, we're going to keep things basic and use:

Install required Python packages:

pip install cryptography

Learn Encryption Basics

Encryption is the most critical component of a password manager.

We will employ Fernet symmetric encryption from the cryptography library. Here's how it works:

We’ll derive the encryption key from your master password using a Key Derivation Function (KDF) — specifically PBKDF2HMAC.

Setting Up the Master Password

When the user opens the app, ask for the master password. Use it to derive the encryption key.

Here’s how to derive the key:

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

def get_key_from_password(password, salt):
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100_000,
        backend=default_backend()
    )
    return base64.urlsafe_b64encode(kdf.derive(password.encode()))

Encrypt and Decrypt Passwords

With the derived key, encrypt and decrypt the stored passwords:

from cryptography.fernet import Fernet

def encrypt_password(key, password):
    fernet = Fernet(key)
    return fernet.encrypt(password.encode())

def decrypt_password(key, token):
    fernet = Fernet(key)
    return fernet.decrypt(token).decode()

Storing Data with SQLite

With SQLite, store:

Create the database and table:

import sqlite3

def create_db():
    conn = sqlite3.connect('vault.db')
    c = conn.cursor()
    c.execute('''
        CREATE TABLE IF NOT EXISTS passwords (
            id INTEGER PRIMARY KEY,
            website TEXT NOT NULL,
            username TEXT NOT NULL,
            password BLOB NOT NULL
        )
    ''')
    conn.commit()
    conn.close()

Saving and Retrieving Passwords

Here's how to save an entry:

def save_password(website, username, password, key):
    encrypted = encrypt_password(key, password)
    conn = sqlite3.connect('vault.db')
    c = conn.cursor()
    c.execute('INSERT INTO passwords (website, username, password) VALUES (?, ?, ?)',
              (website, username, encrypted))
    conn.commit()
    conn.close()

To retrieve and decrypt:

def get_passwords(key):
    conn = sqlite3.connect('vault.db')
    c = conn.cursor()
    c.execute('SELECT website, username, password FROM passwords')
    for row in c.fetchall():
        website, username, encrypted_pw = row
        decrypted_pw = decrypt_password(key, encrypted_pw)
        print(f'Website: {website} | Username: {username} | Password: {decrypted_pw}')
    conn.close()

Protect Your Master Key and Salt

When setting the master password for the first time:

def load_or_create_salt():
    if not os.path.exists('salt.bin'):
        salt = os.urandom(16)
        with open('salt.bin', 'wb') as f:
            f.write(salt)
    else:
        with open('salt.bin', 'rb') as f:
            salt = f.read()
    return salt

Final Program Flow

A simple interface could be as follows:

def main():
    salt = load_or_create_salt()
    master_pw = input("Enter your master password: ")
    key = get_key_from_password(master_pw, salt)

    while True:
        choice = input("1. Save Password\n2. View Passwords\n3. Exit\nChoose: ")
        if choice == '1':
            site = input("Website: ")
            user = input("Username: ")
            pw = input("Password: ")
            save_password(site, user, pw, key)
        elif choice == '2':
            get_passwords(key)
        else:
            break

if __name__ == "__main__":
    create_db()
    main()

Security Best Practices

To make your password manager really secure:

Final Thoughts

Building a safe password manager isn't only a fun project — it's an active learning experience for encryption, secure storage, and security best practices. You can use it yourself or simply build it for learning purposes, either way, the project will take your knowledge of security basics to the next level.

If you'd prefer the entire source code as a GitHub repo or would like to take this on to the web version, give me a shout. I'd be happy to help take it further!