Observed since 20 Oct, 20:52 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
AES-256-GCM encryption with Argon2id key derivation. Self-contained JSON payloads, no shared state.
A symmetric encryption module implementing AES-256-GCM with Argon2id key derivation, following established envelope encryption patterns (similar to JWE/Fernet). Payloads are self-contained JSON blobs — no shared state or config files required to decrypt.
Built to understand authenticated encryption, KDF parameter binding, and defensive input validation from first principles rather than wrapping a high-level library.
cryptography library provides internally. The Python runtime itself is not side-channel resistant. Do not use in contexts where an attacker can measure execution time or power consumption.cryptography library or the underlying OpenSSL implementation has a vulnerability, this module inherits it. No independent verification of primitive correctness is performed.os.urandom uniqueness.| Property | Detail |
|---|---|
| Cipher | AES-256-GCM (authenticated encryption) |
| Key derivation | Argon2id |
| KDF defaults | ops=3, memory=64 MiB, p=4, key_len=32 — exceeds OWASP 2023/2024 minimum baseline (19 MiB / 2 iterations). p=4 is not an OWASP recommendation; parallelism should be tuned to deployment hardware. |
| KDF floor (decrypt) | ops ≥ 2, memory ≥ 32 MiB, p ∈ [1, 16] — weaker than defaults; exists for backwards compatibility, not as a security target |
| Salt | 16 bytes, random per encryption |
| Nonce | 12 bytes, random per encryption (NIST standard) |
| Auth tag | 16 bytes, appended to ciphertext by GCM |
| AAD | Version + KDF params + salt + nonce bound to ciphertext |
| Payload limit | 100 MiB (enforced before encryption and after parsing) |
Peak RAM during a single encrypt/decrypt operation is roughly 3× the payload size (~300 MiB for a 100 MiB payload) due to base64 encoding, intermediate string allocations, and ciphertext byte arrays existing simultaneously.
| Version | AAD includes key_len | Status |
|---|---|---|
1.0 | No | Supported (read-only) |
2.0 | Yes | Current |
New payloads are always written as v2.0. v1.0 payloads can be decrypted without any migration step.
Web UI: A modern browser. No install.
Python CLI / library:
cryptography>=44.0.0 (installed automatically)pip install aes-secure-vault
For development (includes pytest and Hypothesis):
pip install aes-secure-vault[dev]
The recommended way to open it:
python -m http.server 8000
Then visit http://localhost:8000 in your browser. This avoids browser security restrictions on WASM loaded via file://.
Alternatively, double-click index.html in File Explorer or run start index.html — this works in most browsers but may fail silently in some (Chrome in particular blocks WASM from file://).
# Encrypt a file (passphrase prompted securely via stdin, with confirmation)
secure-vault encrypt --file secret.txt --out secret.enc
# Encrypt inline text
secure-vault encrypt --text "my secret data" --out secret.enc
# Decrypt to stdout
secure-vault decrypt --file secret.enc
# Decrypt binary payload to file
secure-vault decrypt --file secret.enc --out recovered.bin --bytes
python -m secure_vault also works as an alternative to secure-vault.
On encrypt, the CLI prompts for the passphrase twice to prevent typos. Ctrl+C exits cleanly at any prompt.
from secure_vault import SecureVault
vault = SecureVault()
# Encrypt (str or bytes)
blob = vault.encrypt("my secret data", "a-strong-passphrase-here")
blob = vault.encrypt(b"\x00\xFF binary data", "a-strong-passphrase-here")
# Decrypt to str (default)
plaintext = vault.decrypt(blob, "a-strong-passphrase-here")
# Decrypt to raw bytes
raw = vault.decrypt(blob, "a-strong-passphrase-here", return_bytes=True)
The encrypted blob is a JSON string safe to store or transmit:
{
"header": {
"v": "2.0",
"kdf": { "ops": 3, "mem": 65536, "p": 4, "key_len": 32 },
"salt": "<base64>",
"nonce": "<base64>"
},
"ciphertext": "<base64 ciphertext + auth tag>"
}
| Exception | Cause |
|---|---|
ValueError | Empty data, empty passphrase, payload too large, malformed structure, unsupported version, invalid KDF params |
DecryptionError | Wrong passphrase, modified ciphertext, or tampered header (AAD failure) |
RuntimeError | Insufficient memory for Argon2, unexpected crypto error, or decrypted data is not valid UTF-8 |
# Full suite (includes Hypothesis fuzz tests — may take a few minutes)
pytest test_secure_vault.py -v
# Skip slow fuzz tests
pytest test_secure_vault.py -v -k "not arbitrary"
Coverage includes: roundtrip correctness, non-determinism verification, authentication/integrity failures, KDF boundary enforcement, type evasion guards, malformed payload rejection, OOM limits, MemoryError path, legacy v1.0 decryption, and property-based fuzzing with Hypothesis.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 1.0.1 | 3 Apr 2026 | 3 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 20:52 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:be2753540a727af79f8da4c370c213bd33774b8aabfbb7d324b6f4752b6ae0c5