____ _ _ ___
/ ___|(_)_ __ | |__ ___ _ __|/ _ \ _ __ ___
| | | | '_ \| '_ \ / _ \ '__| | | | '_ \/ __|
| |___ | | |_) | | | | __/ | | |_| | |_) \__ \
\____|_| .__/|_| |_|\___|_| \___/| .__/|___/
|_| |_|
Zero dependency. Python standard library only. Track E — Zero Dependency Hackathon 2026.
I built CipherOps for the Zero Dependency Hackathon 2026 because most security tools are
a thin wrapper around five npm/PyPI packages. I wanted to see how far I could get composing
the primitives the language already ships — hashlib, hmac, secrets, struct, base64 —
without importing a single third-party library. The answer turned out to be: pretty far.
CipherOps is a unified security CLI with three integrated components sharing one crypto engine:
| Component | What it replaces | stdlib used |
|---|---|---|
| Encrypted Vault | cryptography, passlib, keyring |
hashlib, hmac, secrets, json |
| TOTP / 2FA Generator | pyotp (~1.9M downloads/week) |
hmac, struct, base64, hashlib |
| Secrets Scanner | detect-secrets, truffleHog |
re, math, pathlib, os |
# Run the entire tool — one file, no install
python cipherops.py --help
# Run the full test suite (38 tests)
python -m unittest discover -s tests -p "test_*.py"$ python cipherops.py init
Set master password for new vault: ········
Confirm master password: ········
[+] Encrypted vault successfully initialized at: ~/.cipherops_vault.bin
$ python cipherops.py add github_pat ghp_xxxxxxxxxxxxxxxxxxxx
Enter master password: ········
[+] Secret 'github_pat' successfully encrypted and stored.
$ python cipherops.py list
Enter master password: ········
Stored Secrets:
- github_pat
$ python cipherops.py get github_pat
Enter master password: ········
ghp_xxxxxxxxxxxxxxxxxxxx
$ python cipherops.py totp add github JBSWY3DPEHPK3PXP
Enter master password: ········
[+] TOTP seed for 'github' saved to vault.
$ python cipherops.py totp code github
Enter master password: ········
Current TOTP code for 'github': 492039
$ python cipherops.py scan ./myproject
[*] Scanning './myproject' for exposed credentials...
=== CipherOps Secrets Scan Report ===
[!] DETECTED 2 POTENTIAL SECRET(S):
[HIGH] AWS Access Key ID at ./myproject/config.py:12
Redacted Value: AKIA***REDACTED*** (Entropy: 3.68)
[MEDIUM] Generic API Key / Secret Token at ./myproject/.env.bak:3
Redacted Value: sk_l***REDACTED*** (Entropy: 4.12)
==================================================
[!] REMEDIATION NOTICE:
Committed credentials are COMPROMISED — revoke them at the provider first.
CipherOps can store your NEW replacement credential in the vault.
Rotate & vault NEW replacement for 'AWS Access Key ID'? [y/N]: y
Vault Secret Name [aws_access_key_id]: aws_prod_key
Enter NEW replacement value for 'aws_prod_key': ········
[+] Saved replacement secret 'aws_prod_key' into vault!
Why not store the found secret? Because it's already in git history — storing a compromised credential doesn't undo the exposure. CipherOps flags it, tells you to revoke it, and only stores the new replacement after rotation.
python cipherops.py init # Create new encrypted vault
python cipherops.py add <NAME> <VALUE> # Store a secret
python cipherops.py get <NAME> # Retrieve a secret
python cipherops.py list # List all secret names (never values)
python cipherops.py totp add <NAME> [SEED] # Add TOTP seed (auto-generates if omitted)
python cipherops.py totp code <NAME> # Print current 6-digit TOTP code
python cipherops.py scan <PATH> # Scan for leaked credentials
python cipherops.py scan <PATH> --no-interactive # Scan only, skip remediation prompts
# Options available on every command:
# --vault PATH Use a custom vault file instead of the default
# --password TEXT Pass master password inline (or set CIPHEROPS_PASSWORD env var)CipherOps does not invent a cipher. It composes five standard RFC primitives:
Master Password
│
▼
hashlib.scrypt (N=16384, r=8, p=1) ← CPU + memory-hard key stretching
│
▼
master_key (32 bytes)
│
├─── HKDF-Extract + HKDF-Expand (RFC 5869) with info="cipherops-enc-v1"
│ └──► key_enc (32 bytes) ← Encrypts the payload
│
└─── HKDF-Extract + HKDF-Expand (RFC 5869) with info="cipherops-mac-v1"
└──► key_mac (32 bytes) ← Authenticates the entire file
Encryption: HMAC-SHA256(key_enc, nonce + counter) XOR plaintext ← CTR mode
Auth tag: HMAC-SHA256(key_mac, header_bytes + ciphertext) ← Encrypt-Then-MAC
Verification: hmac.compare_digest(tag, expected) ← Constant-time, BEFORE decryption
Two subkeys are always derived — one for encryption, one for authentication — so the same key never does two jobs.
Protects against:
- Ciphertext or header tampering — any bit flip anywhere raises
ValueError, no garbage output - Malicious vault headers —
scryptparameters are bounds-checked before key derivation runs (prevents memory exhaustion attacks) - Timing side-channels — MAC comparison uses
hmac.compare_digestthroughout - Nonce reuse — all nonces are
secrets.token_bytes(16)(CSPRNG)
Does not protect against:
- Keyloggers or OS-level memory access capturing the master password at entry time
- Weak master passwords — the strength of scrypt is bounded by the password you choose
| Operation | Time |
|---|---|
| Vault init (scrypt N=16384, r=8, p=1) | ~37 ms |
| Secret add + get round-trip | ~124 ms |
| Directory scan (50 files) | ~30–370 ms |
The scrypt cost parameters N, r, p are tunable. Increasing N makes brute-force attacks
harder; decreasing it makes operations faster. The defaults are a reasonable balance for
a local developer tool.
The TOTP generator reimplements pyotp using nothing but hmac, struct, and base64:
1. Decode the Base32 secret key
2. Compute T = floor(unix_timestamp / 30) ← 30-second window
3. HMAC-SHA1(secret_bytes, T as 8-byte big-endian) → 20-byte digest
4. Dynamic truncation: offset = digest[-1] & 0x0F
5. Extract 4 bytes at offset, mask the top bit → 31-bit integer
6. code = integer % 10^6 → zero-padded 6-digit string
Verified against the official RFC 6238 Appendix B test vectors (SHA-1 and SHA-256).
The scanner combines two independent signals to reduce false positives:
- Pattern matching — regex patterns for AWS Access Keys, GitHub PATs, private key headers, Slack tokens, and JWTs.
- Shannon entropy scoring —
H = -Σ p(c) log₂ p(c). A 40-character uniform string likeaaaaaaaaaascores ~0.0 bits. A real API key scores >4.5 bits.
Confidence tiers:
HIGH— signature pattern matched (e.g.AKIA...) OR entropy > 4.5 bitsMEDIUM— generic pattern + entropy 3.5–4.5 bitsLOW— pattern matched but low entropy (likely a placeholder or hash, not a live credential)
requirements.txt is empty. Running pip install -r requirements.txt installs 0 packages.
$ python -c "
import sys, cipherops
stdlib = sys.base_prefix
non_std = [m for m in sys.modules.values()
if hasattr(m, '__file__') and m.__file__
and not m.__file__.startswith(stdlib)
and 'CipherOps' not in m.__file__]
print('Third-party modules loaded at runtime:', len(non_std))
"
Third-party modules loaded at runtime: 0All standard library modules used: argparse, base64, collections, getpass, hashlib,
hmac, json, math, os, pathlib, re, secrets, struct, sys, time, typing.
The complete implementation lives in one readable file — cipherops.py — which can be read
top to bottom and understood. The src/ directory is the pre-consolidation modular version,
kept for readability. tests/test_parity.py proves both produce identical outputs.
A Python source file is deterministic by definition. Two SHA-256 runs produce the same hash:
Run 1 SHA-256: ca2200e0588153f7100cfc4ab888ea71a36a6f69446b5476746f7de02d98feee
Run 2 SHA-256: ca2200e0588153f7100cfc4ab888ea71a36a6f69446b5476746f7de02d98feee
| Package Killed | Weekly Downloads | Replaced with |
|---|---|---|
cryptography |
~353M/week | hashlib + hmac + secrets (RFC 5869 HKDF + CTR + Encrypt-Then-MAC) |
passlib |
~9.1M/week | hashlib.scrypt |
pyotp |
~1.9M/week | hmac + struct + base64 (RFC 6238) |
See STDLIB.md for all 11 substitutions with rationales. (Source: pypistats.org, Aug 2026)
cipherops.py ← Single-file executable (canonical submission artifact)
src/
crypto.py ← RFC 5869 HKDF, scrypt, CTR mode, Encrypt-Then-MAC
vault.py ← Encrypted JSON secret store
totp.py ← RFC 6238 / RFC 4226 TOTP engine
scanner.py ← Secrets scanner with entropy scoring
cli.py ← argparse CLI surface
tests/
test_crypto.py ← RFC 5869 Test Case 1, tamper resistance, scrypt bounds
test_vault.py ← Persistence, wrong password, disk round-trips
test_totp.py ← RFC 6238 Appendix B test vectors (SHA-1 & SHA-256)
test_scanner.py ← Entropy tiering, redaction, binary file skipping
test_cli.py ← Full CLI lifecycle, ANSI color suppression
test_parity.py ← cipherops.py vs src/ byte-for-byte output match
test_single_file.py ← Single-file artifact verification
README.md ← This file
STDLIB.md ← All stdlib-for-package substitutions
LICENSE ← MIT
requirements.txt ← Empty
deps-proof.txt ← Runtime audit log
.zero-dep.toml ← Track E, one-line pitch
Makefile ← make test / make proof / make hash
python -m unittest discover -s tests -p "test_*.py"
# Ran 38 tests in ~2s — OKIndividual test files can be run directly:
python -m unittest tests.test_crypto # RFC 5869 verification
python -m unittest tests.test_totp # RFC 6238 vectors
python -m unittest tests.test_parity # single-file / src parity- The cipher is a composed construction, not a formally verified AEAD like AES-GCM. It is resistant to the attacks listed above and correct under the standard assumptions for HMAC-based constructions, but it has not been audited by a cryptographer.
http.serveris not used. This is a pure CLI tool.- The vault is a single encrypted file. There is no concurrency control — two processes writing simultaneously will corrupt it.
- The scanner generates false positives at LOW confidence. This is intentional and documented.
MIT — Copyright 2026 developerHarish2007