VaultLite is a lightweight HashiCorp Vault alternative. Every byte of the AES-128 cipher is hand-coded from the NIST spec. No cryptography, no pycryptodome — just Python stdlib.
Every transformation. S-Box substitution from the GF(2⁸) inversion table. ShiftRows and MixColumns with explicit Galois Field arithmetic. Key expansion from 16 bytes into 11 round keys. Validated against the NIST FIPS 197 Appendix B test vector — the same spec Intel follows for AES-NI.
# NIST FIPS 197 Appendix B — the standard AES-128 test vector
key = 2b7e1516 28aed2a6 abf71588 09cf4f3c
plaintext = 3243f6a8 885a308d 313198a2 e0370734
expected = 3925841d 02dc09fb dc118597 196a0b32 ✓ matches
It manages secrets the way production systems do. Envelope encryption gives each secret its own key. The seal/unseal ceremony protects the master key by splitting it into shares. Token-based auth, path-based policies, TTL leases, version history, and a hash-chained audit trail that detects tampering.
┌─────────────────────────────────────────────────────────┐ │ HTTP API (25+ endpoints) │ ├─────────────────────────────────────────────────────────┤ │ Vault Orchestrator │ ├─────────┬─────────┬─────────┬─────────┬─────────────────┤ │ Auth │ Policy │ Audit │ Lease │ Versioning │ │ Tokens │ ACL │ Hash │ TTL │ History │ │ AppRole │ Glob │ Chain │ Renewal │ Soft-delete │ ├─────────┴─────────┴─────────┴─────────┴─────────────────┤ │ Seal Manager (XOR key splitting) │ ├─────────────────────────────────────────────────────────┤ │ Envelope Encryption (AES-128 from scratch) │ ├─────────────────────────────────────────────────────────┤ │ Memory Store │ File Store │ SQLite Store │ └─────────────────────────────────────────────────────────┘
Three lines to start. Initialize the vault, unseal it with your key shares, then write and read secrets. Works as a library or as an HTTP server.
from vaultlite.vault import Vault
vault = Vault()
result = vault.initialize(shares=3, threshold=3)
for share in result.unseal_keys:
vault.unseal(share)
vault.write("secret/db/prod", {
"password": "s3cur3_p@ss!",
}, result.root_token)
secret = vault.read("secret/db/prod", result.root_token)
print(secret["data"]["password"]) # s3cur3_p@ss!
Path-based policies with glob matching. Create a read-only policy for your database team, a full-access policy for admins. Tokens inherit their parent's policies. Revoke a parent and all children get revoked too.
# Create a read-only policy
db_reader = Policy(
name="db-reader",
rules=[Rule(path="secret/database/*", capabilities=["read", "list"])]
)
vault.put_policy("db-reader", db_reader, root_token)
# Create a token with that policy
reader = vault.create_token(root_token, policies=["db-reader"])
# This works
vault.read("secret/database/prod", reader.token_id)
# This raises AuthorizationError
vault.write("secret/database/prod", {...}, reader.token_id)
Every operation is logged with a SHA-256 hash chain. Each entry contains the hash of the previous entry — like a blockchain for your audit log. Tamper with any entry and verify_chain() catches it.
entries = vault.audit_log(token, limit=10)
# [write] secret/database/prod → allow (by hvs.root-xyz...)
# [read] secret/database/prod → allow
# [read] secret/api/stripe → deny (no 'read' capability)
integrity = vault.verify_audit_chain(token)
# {"valid": True, "total_entries": 47}