Skip to content

Latest commit

 

History

History
652 lines (426 loc) · 14.2 KB

File metadata and controls

652 lines (426 loc) · 14.2 KB

🔐 PyVault

PyVault is a local password and secrets manager written in Python.

The goal of this project is to build a simple, private and secure way to store sensitive information locally while learning how encryption, databases, web development and application architecture work.

⚠️ PyVault is currently under development.


✨ Features

CLI — python main.py

  • 🔑 Generate Fernet encryption keys
  • 🛡️ On Windows, protect the key on-disk with DPAPI (dpapi_utils.py) instead of storing it in plain text
  • 🔐 Encrypt passwords using Fernet, then store them in a SQLite database (secret/passwords.db)
  • 🔓 Decrypt and retrieve stored passwords (handles duplicate website entries)
  • 📋 List all saved entries
  • 🔎 Search stored passwords
  • 🗑️ Delete passwords
  • 📤 Export passwords as a zip archive
  • 🖥️ Simple CLI interface with ASCII banner
  • 🧪 Unit tests (tests/)
  • 📊 Encryption / decryption benchmark (Jupyter notebook)

Web — docs/

A static site deployed on GitHub Pages that mirrors PyVault's features in the browser:

  • 🖥️ An interactive terminal reproducing the CLI (python main.py) directly in the browser
  • 🔐 The real Fernet algorithm re-implemented in JavaScript (fernet.js) using the Web Crypto API — data produced in the browser can be decrypted by the Python CLI and vice-versa
  • 💾 Vault entries stored in the browser's localStorage
  • 📤 Zip export built directly in the browser
  • 🌍 Bilingual Français / 日本語 interface with an i18n system
  • 📄 README, ideas, tests and "about" pages rendered as a single-page site

Platform support

  • 🪟 Windows benefits from DPAPI key protection
  • 🖥️ macOS and Linux are supported by the same clear-screen helper logic

🧠 Why PyVault?

I wanted to create a project that was more than a simple Python script.

PyVault is also a way for me to learn how different parts of a real application work together:

  • Python
  • Cryptography
  • Databases
  • Web development (HTML / CSS / JavaScript)
  • APIs
  • Authentication
  • Security
  • Software architecture
  • Performance testing

Instead of only following tutorials, I want to build the project myself, encounter problems, research solutions and document the entire process.


🏗️ Architecture

The architecture below shows both the current project and the features planned for the future.

flowchart TD

    User["👤 User"]

    PyVault["🔐 PyVault"]

    CLI["🖥️ CLI<br/>CURRENT"]

    WebTool["🖥️ Web Tool (docs/)<br/>CURRENT"]

    GenerateKey["🔑 Generate Key<br/>CURRENT"]

    AddPassword["🔐 Add Password<br/>CURRENT"]

    ListPasswords["📋 List Passwords<br/>CURRENT"]

    DecryptPassword["🔓 Decrypt Password<br/>CURRENT"]

    Fernet["🔒 Fernet Encryption<br/>CURRENT"]

    JsFernet["🔒 Fernet in JS (fernet.js)<br/>CURRENT"]

    KeyFile["📄 key.txt (DPAPI on Windows)<br/>CURRENT"]

    Database["🗄️ SQLite (secret/passwords.db)<br/>CURRENT"]

    DPAPI["🛡️ DPAPI Key Protection (win32)<br/>CURRENT"]

    Search["🔎 Search Passwords<br/>CURRENT"]

    Delete["🗑️ Delete Password<br/>CURRENT"]

    Export["📤 Export Passwords<br/>CURRENT"]

    Tests["🧪 Unit Tests<br/>CURRENT"]

    Benchmark["📊 Benchmark<br/>CURRENT"]

    I18n["🌍 FR / JA i18n<br/>CURRENT"]

    MasterPassword["🔑 Master Password<br/>PLANNED"]

    Vault["🔐 Vault System<br/>PLANNED"]

    API["🌐 Local API<br/>PLANNED"]

    FastAPI["⚡ FastAPI<br/>PLANNED"]

    Web["🖥️ Web Interface<br/>PLANNED"]

    User --> PyVault

    PyVault --> CLI
    PyVault --> WebTool

    CLI --> GenerateKey
    CLI --> AddPassword
    CLI --> ListPasswords
    CLI --> DecryptPassword

    GenerateKey --> Fernet
    GenerateKey --> KeyFile
    GenerateKey --> DPAPI

    AddPassword --> Fernet
    Fernet --> Database

    DecryptPassword --> Database
    ListPasswords --> Database

    CLI --> Search
    CLI --> Delete
    CLI --> Export

    WebTool --> GenerateKey
    WebTool --> AddPassword
    WebTool --> ListPasswords
    WebTool --> DecryptPassword

    WebTool --> JsFernet
    JsFernet --> I18n

    MasterPassword -.-> Vault
    Vault -.-> SQLite

    API -.-> FastAPI
    FastAPI -.-> Vault
    Web -.-> API

    Tests -.-> PyVault
    Benchmark -.-> Fernet
Loading

CURRENT = already implemented

PLANNED = planned for a future version


📁 Current Project Structure

PyVault/

│
├── commands/             ← CLI commands
│   ├── add.py
│   ├── decrypt.py
│   ├── delete.py
│   ├── export.py
│   ├── generate_key.py
│   ├── list.py
│   └── search.py
│
├── tests/                ← unit tests
│   ├── add_test.py
│   ├── benchmark.ipynb   ← Jupyter benchmark
│   ├── decrypt_test.py
│   ├── test_system_info.py
│   └── test_unitary/
│
├── docs/                 ← static website (GitHub Pages)
│   ├── index.html        ← single-page site (FR / JA)
│   ├── robots.txt
│   ├── sitemap.xml
│   └── static/
│       ├── css/styles.css
│       └── js/
│           ├── fernet.js ← Fernet re-implemented in JS (Web Crypto)
│           ├── tool.js   ← interactive browser terminal
│           ├── main.js   ← page routing & mermaid
│           └── i18n.js   ← FR / JA translations
│
├── secret/               ← password storage (DB + legacy files)
│   ├── passwords.db      ← SQLite database
│   └── github.txt
│
├── images/
│   └── new_benchmark.png ← encryption/decryption benchmark
│
├── examples/
│
├── .github/workflows/    ← GitHub Pages deploy (`static.yml`)
│
├── idea/
│   └── idea.md           ← ideas file
│
├── japanese/             ← Japanese version of the code
│
├── dpapi_utils.py        ← DPAPI protect / unprotect helper (Windows)
├── main.py
├── system_info.py
├── key.txt               ← protected Fernet key
├── SECURITY.md
├── .gitignore
├── LICENSE
└── README.md

📌 Note: add.py, list.py and decrypt.py now store passwords in a SQLite database (secret/passwords.db). The search.py and delete.py commands still operate on the legacy per-website files in secret/.


🔐 Current Encryption System

PyVault uses Fernet from the cryptography library.

A key is generated with:

key = Fernet.generate_key()

The key is stored locally in key.txt. On Windows, the raw key is wrapped with the DPAPI functions in dpapi_utils.py (protect() / unprotect()) so it is not stored in plain text on disk. On other platforms the key is stored as-is.

When adding a password, PyVault encrypts it before storing it:

cipher = Fernet(key.encode())

encrypted = cipher.encrypt(passwd.encode())

The encrypted password is then inserted into the passwords table of the SQLite database:

secret/passwords.db

The password itself is not stored in plain text.

The browser-side terminal re-implements the same Fernet scheme in JavaScript (docs/static/js/fernet.js) using the Web Crypto API (AES-CBC + HMAC-SHA256). Because it follows the Fernet token format, tokens created in the browser are compatible with the Python CLI and the other way around.

⚠️ This is an early prototype. Even with DPAPI key protection on Windows, the system is not considered secure enough for production use (no master password yet).


📊 Benchmark

PyVault includes a benchmark using Jupyter Notebook to measure the performance of Fernet encryption and decryption.

The benchmark tests multiple data sizes, from a few bytes up to 1 MB, and performs multiple iterations for each size.

The results are visualized in the following graph:

PyVault Encryption / Decryption Benchmark

The benchmark helps measure how encryption and decryption performance changes as the amount of data increases.

The benchmark notebook is located at:

tests/benchmark.ipynb

It can be used to experiment with PyVault's encryption system and compare future implementations.


🚀 Installation

Clone the repository:

git clone https://github.com/KirobotDev/PyVault.git

cd PyVault

Create a virtual environment:

Windows

python -m venv .venv

.venv\Scripts\activate

Linux / macOS

python3 -m venv .venv

source .venv/bin/activate

Install dependencies:

pip install -r requirements.txt

▶️ Usage

CLI

Start PyVault:

python main.py

You will see:

S. [Stars Project]      0. [Generate Key (Obliged)]     Q. [Leave]

        1. [Add Password]   4. [Export (Zipfiles)]
        2. [List Pswd]      5. [Delete Passwd]
        3. [Decrypt Pswd]   6. [Search Website]

        Choice: 

Generate a key

Choose:

0

PyVault will generate a Fernet key and save it to key.txt (protected with DPAPI on Windows).

Add a password

Choose:

1

PyVault will ask for:

Enter the name of your website (e.g. github):
Enter your password:

The password will be encrypted and stored in the SQLite database (secret/passwords.db).

List saved entries

Choose:

2

PyVault will display every website stored in the database.

Decrypt a password

Choose:

3

PyVault will ask for:

Enter the name of the website:

If several passwords exist for the same website, you will be asked to pick one. It will then display:

Website: github
Your password is: your_password_here

Web tool (browser)

The interactive terminal is available on the site's Test page (or by opening docs/index.html locally). It behaves exactly like the CLI but runs entirely in your browser:

0  Generate a key
1  Add a password
2  List entries
3  Decrypt a password
4  Export (zip)
5  Delete an entry
6  Search a site
s  Open the GitHub repo
q  Quit
help / clear

Entries are saved in the browser's localStorage. Toggle the interface between Français and 日本語 with the language button in the top bar.


🧪 Running Tests

Unit tests are available in the tests/ folder.

Run them with:

python -m unittest tests.test_system_info

You can also inspect the manual sanity tests in tests/add_test.py and tests/decrypt_test.py which encrypt and decrypt a fixed password with a hardcoded key.


📊 Running the Benchmark

The benchmark is available as a Jupyter Notebook.

Install Jupyter if necessary:

pip install jupyter

Start Jupyter:

jupyter notebook

Then open:

tests/benchmark.ipynb

The benchmark measures:

  • Encryption speed
  • Decryption speed
  • Different data sizes (1 B → 1 MB)
  • Average execution time
  • Performance scaling

🛠️ Roadmap

Phase 1 — Prototype

  • Generate Fernet key
  • Save key locally
  • Encrypt passwords
  • Store encrypted data
  • Store website information
  • Basic CLI
  • Decrypt passwords
  • List saved entries

Phase 2 — Vault

  • Search passwords
  • Delete passwords
  • Export passwords
  • Web tool in the browser (docs/)
  • Fernet re-implemented in JavaScript (Web Crypto)
  • Bilingual FR / JA website (i18n)
  • Load existing key automatically

Phase 3 — Security

  • DPAPI key protection on Windows
  • Master password
  • KDF-based key derivation
  • Vault locking
  • Failed-attempt protection
  • Security tests
  • Security policy (SECURITY.md)

Phase 4 — Database

  • SQLite
  • Database models
  • Encrypted database fields
  • Data validation
  • Database migrations
  • Migrate search and delete to the database

Phase 5 — API

  • Local API
  • FastAPI
  • Authentication
  • API documentation

Phase 6 — Interface

  • Full web interface
  • Vault dashboard
  • Password manager UI
  • API integration

Phase 7 — Open Source

  • Complete documentation
  • Automated tests
  • GitHub Pages deployment (CI/CD)
  • Security review
  • PyPI package

🔒 Security

PyVault is an experimental learning project and is not intended for production use.

On Windows, the Fernet key stored in key.txt is wrapped with the DPAPI functions in dpapi_utils.py, which binds access to the Windows user account. Without a master password, however, anyone with access to the user session and files could still recover the data.

See SECURITY.md for the supported versions and how to responsibly report a vulnerability.


🌍 Website

PyVault has a static website in the docs/ folder, automatically deployed to GitHub Pages on every push to main (see .github/workflows/static.yml).

It includes:

  • An interactive browser terminal reproducing the CLI
  • The README, ideas, tests and about pages
  • A Français / 日本語 language switch

📚 Development Story

PyVault isn't only a software project.

I also want to document the process of building it.

The documentation will cover:

Idea

  ↓

First prototype

  ↓

Encryption

  ↓

Problems

  ↓

Research

  ↓

Solutions

  ↓

Security

  ↓

Testing

  ↓

Benchmarking

  ↓

Final application

The objective is to show what I learned, what went wrong and how the project evolved over time.


🧪 Status

Current version: 0.2.0-dev

PyVault is currently an experimental project.

The project is actively being developed and its architecture may change significantly.


🤝 Contributing

Contributions, suggestions and bug reports are welcome.

If you find a problem, feel free to open an issue.

For larger changes, please open an issue first to discuss the idea.

Good first issues are listed in main.md, including adding a Japanese codebase, testing macOS, and creating a custom encryption algorithm.


📄 License

PyVault is released under the MIT License.

See LICENSE for more information.


👤 Author

xql

GitHub: https://github.com/KirobotDev


Built with Python 🐍 & JavaScript ⚡

Learning by building.