Metadata-Version: 2.4
Name: larzvault
Version: 0.1.0
Summary: Encrypted secrets manager: passphrase-locked vault file (scrypt + ChaCha20-Poly1305) with env injection. Pure Python.
Author: larz-scripter
License: MIT
Project-URL: Homepage, https://github.com/larz-scripter/larzvault
Project-URL: Repository, https://github.com/larz-scripter/larzvault
Project-URL: Documentation, https://github.com/larz-scripter/larzvault#readme
Project-URL: Issues, https://github.com/larz-scripter/larzvault/issues
Keywords: secrets,secrets-management,vault,encryption,dotenv,credentials,scrypt,chacha20poly1305,config,pure-python
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: larzcrypt>=0.1.1
Dynamic: license-file

# larzvault

**An encrypted secrets manager in pure Python.**

Keep your API keys, tokens, and connection strings in one file, encrypted under a
master passphrase — instead of scattered across plaintext `.env` files, shell
history, and screenshots. Open the vault with the passphrase, read your secrets,
inject them into the environment. Done.

```python
from larzvault import Vault

v = Vault.create("secrets.vault", "master passphrase")
v.set("STRIPE_KEY", "sk_live_...")
signing = v.generate("SIGNING_KEY")        # strong random secret, stored + returned
v.save()

# later, elsewhere
v = Vault.open("secrets.vault", "master passphrase")
v.get("STRIPE_KEY")
v.to_env()                                 # every secret into os.environ
```

## Why

- **Real authenticated encryption.** The master key is derived from your
  passphrase with **scrypt** (memory-hard, so brute-forcing is expensive) and the
  secrets are sealed with **ChaCha20-Poly1305**. A wrong passphrase or a single
  tampered byte raises `WrongPassphrase` — it never returns garbage or silently
  weakens itself.
- **The KDF settings are authenticated too.** An attacker can't edit the file to
  downgrade the scrypt cost — the parameters are covered by the AEAD tag.
- **One portable file.** Commit it to a private repo, drop it on a server, back it
  up — it's useless without the passphrase.
- **Drop-in env injection.** `to_env()` loads secrets straight into
  `os.environ`, so existing `os.environ["STRIPE_KEY"]` code just works.
- **Rotation built in.** `generate()` makes strong secrets; `change_passphrase()`
  re-keys the vault with a fresh salt.

## Install

```bash
pip install larzvault
```

Built on **[larzcrypt](https://github.com/larz-scripter/larzcrypt)** (itself pure
Python, zero third-party dependencies) for the cryptography.

## Usage

```python
from larzvault import Vault, WrongPassphrase

# create
v = Vault.create("app.vault", "hunter2")
v.set("DB_URL", "postgres://user:pass@host/db")
v.set("FLAGS", {"beta": True})            # any JSON-serializable value
v.save()

# open (raises WrongPassphrase on a bad passphrase or tampered file)
try:
    v = Vault.open("app.vault", "hunter2")
except WrongPassphrase:
    ...

v.get("DB_URL")
v.keys()                                   # ["DB_URL", "FLAGS"]
v.delete("FLAGS")
v.generate("API_KEY")                      # random, returned + stored
v.to_env(prefix="APP_")                    # os.environ["APP_DB_URL"] = ...
v.change_passphrase("new-stronger-one")    # re-key + save
v.save()
```

## Threat model (read this)

larzvault protects secrets **at rest**: someone who copies your vault file learns
nothing without the passphrase, and can't tamper with it undetected. It does
**not** protect against a compromised running process (once you open the vault or
call `to_env()`, the secrets are in memory/`os.environ` like any app), a
keylogged passphrase, or swap/core-dump leakage. Choose a strong passphrase — the
scrypt cost slows guessing, but a weak passphrase is still a weak passphrase.

## Tests

```bash
python -m unittest discover -s tests -v      # 14 tests incl. tamper + downgrade detection
```

## The Larz stack

Pure-Python, zero-third-party-dependency building blocks:

- **[larz](https://github.com/larz-scripter/larz)** — money-native web framework
- **[larzchain](https://github.com/larz-scripter/larzchain)** — from-scratch PoW blockchain
- **[larzmoney](https://github.com/larz-scripter/larzmoney)** — exact, penny-perfect money
- **[larzcrypt](https://github.com/larz-scripter/larzcrypt)** — pure-Python cryptography toolkit
- **[larzdb](https://github.com/larz-scripter/larzdb)** — crash-safe embedded database
- **[larzagent](https://github.com/larz-scripter/larzagent)** — zero-dep AI agent framework
- **[larzchart](https://github.com/larz-scripter/larzchart)** — data to inline SVG charts
- **[larzmark](https://github.com/larz-scripter/larzmark)** — Markdown + SEO static sites
- **[larztask](https://github.com/larz-scripter/larztask)** — durable background job queue
- **larzvault** — this library

## License

MIT © larz-scripter
