Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyLockbox

Secure, encrypted and easy-to-use object storage for Python applications.

Encrypted Pickle storage · authenticated files · restricted loading · environment configuration

CI Python Version Security License

Getting Started · Environment Variables · Security Model · API · Development


PyLockbox is a general-purpose storage library for Python. It stores application state in a single encrypted and authenticated binary file while providing a simple dictionary-style API for common key/value data.

The package is designed for configuration, sessions, local application state, caches, and other data that should be protected at rest without requiring a database.

Important

Version 2.0.0 is a breaking rewrite. PyLockbox v2 intentionally does not read the previous ez-storage JSON format and does not include a legacy migration layer.

Features

  • Encrypted binary storage using ChaCha20-Poly1305.
  • Separate encryption and integrity keys derived with HKDF.
  • Additional HMAC-SHA256 authentication for the envelope and ciphertext.
  • Restricted Pickle loading with safe built-ins and explicit class registration.
  • No dynamic imports based on data stored in a file.
  • Atomic writes with temporary files, fsync, and replacement.
  • Cross-platform file locking for concurrent access.
  • Rotating backups with configurable retention.
  • File-size and decompression limits to reduce resource-exhaustion risks.
  • Optional compression before encryption.
  • Environment-variable configuration with custom prefixes.
  • Per-call configuration overrides without changing the store defaults.
  • Simple dotted-key mapping access such as profile.name.
  • Python 3.10–3.13 support.

Getting Started

Requirements

  • Python 3.10 or newer
  • cryptography >= 42

Installation

Install the released package from PyPI:

python -m pip install pylockbox

For local development:

git clone https://github.com/Lainupcomputer/PyLockbox.git
cd PyLockbox
python -m pip install -e ".[dev]"

Quick start

PyLockbox requires a 32-byte encryption key. There is no insecure default key.

from pylockbox import SecureStore, encode_key, generate_key

key = generate_key()
print("Store this key outside your repository:", encode_key(key))

store = SecureStore("state.lockbox", key=key)
store.set("profile.name", "Lainup")
store.set("settings.theme", "dark")
store.set("launch_count", 1)
store.save()

reader = SecureStore("state.lockbox", key=key)
print(reader.load())
print(reader.get("profile.name"))

The generated key must be stored securely. Do not commit it to GitHub or place it directly in source code used in production.

save(value) and load() also support Pickle-compatible root objects. The dotted-key helpers require the root object to be a dictionary.

Environment Variables

Use SecureStore.from_env() when configuration should come from the process environment. The default prefix is PYLOCKBOX_.

Variable Default Description
PYLOCKBOX_PATH storage.lockbox Storage file path
PYLOCKBOX_KEY required URL-safe base64 or hex encoded 32-byte key
PYLOCKBOX_MAX_FILE_SIZE 64MiB Maximum storage and decoded payload size
PYLOCKBOX_BACKUPS 3 Number of rotating backups; 0 disables backups
PYLOCKBOX_LOCK_TIMEOUT 5 Lock wait time in seconds
PYLOCKBOX_COMPRESSION true Compress when compression reduces the payload size

Example in Windows PowerShell:

$env:PYLOCKBOX_PATH = "state.lockbox"
$env:PYLOCKBOX_KEY = "paste-a-generated-base64-key-here"
$env:PYLOCKBOX_MAX_FILE_SIZE = "128MiB"
$env:PYLOCKBOX_BACKUPS = "5"
$env:PYLOCKBOX_COMPRESSION = "true"
from pylockbox import SecureStore

store = SecureStore.from_env()
store.set("counter", 1).save()
value = store.load()

Custom prefixes are useful when an application manages more than one store:

store = SecureStore.from_env(prefix="APP_STORAGE_")

Configuration precedence is:

per-call override > constructor argument > environment variable > default

For example, a one-time load override does not modify the store configuration:

value = store.load(key=another_key, max_file_size="256MiB")

PyLockbox reads environment variables but never writes secrets back into os.environ.

Security Model

Every storage file uses a versioned binary envelope rather than JSON:

  1. Pickle serializes the application value.
  2. Supported Pickle opcodes are validated before loading.
  3. The payload is optionally compressed.
  4. ChaCha20-Poly1305 encrypts and authenticates the payload.
  5. HMAC-SHA256 authenticates the header and ciphertext as an additional integrity layer.
  6. A restricted unpickler loads only safe built-ins or classes explicitly registered by the application.

The implementation also applies size limits before reading, bounds decompression, uses atomic file replacement, and protects access with a cross-platform lock.

Important Pickle limitation

Pickle is not a security sandbox. PyLockbox is intended for authenticated application state protected by a trusted key; it is not intended for arbitrary files from untrusted people.

Do not load a file when an attacker controls the Python process, has obtained the encryption key, or can register malicious classes in your application. Register only classes whose deserialization behavior you trust.

User-defined Classes

Custom classes are denied by default. Register the exact class on every process that loads the file:

from dataclasses import dataclass

from pylockbox import SecureStore


@dataclass
class Profile:
    name: str


key = SecureStore.generate_key()

writer = SecureStore("profiles.lockbox", key=key)
writer.register_type(Profile)
writer.save(Profile("Lainup"))

reader = SecureStore("profiles.lockbox", key=key)
reader.register_type(Profile)
profile = reader.load()

print(profile.name)

Explicit registration prevents file data from freely importing arbitrary modules, classes, or functions.

API Overview

API Purpose
SecureStore(path, key=...) Create a configured store
SecureStore.from_env(...) Create a store from environment variables
generate_key() Generate a cryptographically random 32-byte key
encode_key(key) Encode a key for environment variables
store.save(value) Encrypt and save a root value
store.load() Verify, decrypt, and safely load a value
store.set("a.b", value) Set a nested dictionary value
store.get("a.b", default) Read a nested dictionary value
store.remove("a.b") Remove a nested dictionary value
store.keys() / store.items() Inspect dictionary contents
store.register_type(MyClass) Explicitly allow a custom class
store.list_backups() List rotating backup files
store.delete() Delete the main storage file

Development

Run the test suite with the Python standard library:

python -m unittest discover -s tests -v

The GitHub Actions workflow runs the tests on Python 3.10, 3.11, 3.12, and 3.13.

Build and validate the package

The repository includes a publishing helper. It builds and validates the package without uploading anything unless --publish is explicitly provided:

# Build and validate only
python scripts/publish.py --clean

# Recommended first upload
python scripts/publish.py --repository testpypi --publish

# Public PyPI upload after TestPyPI verification
python scripts/publish.py --repository pypi --publish

Windows PowerShell wrapper:

.\scripts\publish.ps1 --clean
.\scripts\publish.ps1 --repository testpypi --publish

Configure upload credentials through Twine's normal mechanisms such as TWINE_USERNAME, TWINE_PASSWORD, a keyring, or .pypirc. Never commit credentials or generated storage keys.

Project Structure

PyLockbox/
├── src/pylockbox/       # Package implementation
├── tests/               # Security and behavior tests
├── scripts/             # Build and publishing helpers
├── pyproject.toml       # Package metadata and tooling
└── README.md            # Documentation

License

PyLockbox is released under the MIT License.

Made for Python applications that need simple, protected local storage.

About

Secure, encrypted and authenticated Pickle storage for Python with restricted loading, environment variables, backups, and a simple key/value API.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages