Quantum-resistant encryption for text and files, in a terminal GUI anyone can operate.
AES-256-GCM · ChaCha20-Poly1305 · ML-KEM-768 · Argon2id
Quick Start · The Wizard · Full Guide · Security Policy · Changelog · Contributing
Most encryption tools make you choose: easy to use or cryptographically serious. MORPHEUS does both.
Every encryption it produces is already quantum-resistant — with no optional package, no key ceremony, and nothing to configure. That is a property of the defaults, not of an add-on: Argon2id has no known quantum shortcut, and AES-256 and ChaCha20 keep roughly 128-bit security against Grover's algorithm. The whole point is that you do not have to do anything to get it.
It wraps that in a terminal GUI anyone can operate — no cryptography degree required.
What sets it apart:
- Quantum-resistant by default — not a mode you have to find and enable
- Cipher chaining — AES-256-GCM then ChaCha20-Poly1305 with independent keys
- Self-describing authenticated format — the header, including the KDF parameters, is covered by the AEAD tag, so cipher, KDF and parameters cannot be tampered with or downgraded
- Optional ML-KEM-768 (FIPS 203) for a second, asymmetric factor: encrypt to someone's public key so that guessing the password is not enough
On the wording. "Post-quantum" is often used to mean "uses a lattice KEM". It is used here in the sense that matters to you: the ciphertext resists an attacker with a quantum computer. Symmetric encryption with a 256-bit key already does. ML-KEM adds a different property, described below.
| MORPHEUS | age | gpg | openssl enc | |
|---|---|---|---|---|
| Quantum-resistant password mode | Yes | Yes | Yes | Yes |
| Quantum-resistant recipient mode | ML-KEM-768 (FIPS 203), optional | No — X25519 | No — RSA/ECC | n/a |
| Cipher chaining | AES + ChaCha | -- | -- | -- |
| Terminal GUI | Full TUI with strength meter | -- | -- | -- |
| File encryption | Up to 100 MiB (any type) | Yes | Yes | Yes |
| Memory protection | Best-effort ctypes.memset zeroing of key buffers |
-- | pinentry | -- |
| Self-describing format | Versioned header, fully AAD-authenticated | Yes | Yes | -- |
| Auto-clear output | 60 s countdown in the TUI | -- | -- | -- |
| KDF | Argon2id / Scrypt | scrypt | S2K | PBKDF2 |
git clone https://github.com/404SecNotFound/Morpheus.git
cd Morpheus && pip install -r requirements.txt
# Launch the GUI
python morpheus.py
# Or encrypt from the command line
python morpheus.py -o encrypt --data "sensitive text"
# Encrypt a file
python morpheus.py -o encrypt -f secret.pdfPost-quantum support:
pip install pqcrypto
Clipboard on Linux: the TUI copies via
pyperclipand falls back toxclip/xsel/wl-copy. If none are installed, copying is unavailable and the TUI offers to write the output to a temporary file instead. See What touches the disk.
- You provide text or a file and a strong password
- The password is stretched through Argon2id (memory-hard: 64 MiB, t=3, p=4) into a 256-bit key
- Your data is encrypted with AES-256-GCM (authenticated encryption)
- The output is a single base64 string you can store anywhere
Every encryption produces different output — even for identical inputs — because a fresh random salt and nonce are generated each time.
Choose your protection level:
| Mode | What Happens | Best For |
|---|---|---|
| Single cipher | AES-256-GCM or ChaCha20-Poly1305 | Everyday encryption |
| Cipher chaining | AES-256-GCM then ChaCha20 with independent keys | Defense against single-algorithm compromise |
| Hybrid PQ | Password key + ML-KEM-768 shared secret combined via HKDF | Encrypting to someone else's public key, with no shared password |
| Maximum | Chaining + Hybrid PQ (all layers) | Highest assurance |
All four are quantum-resistant. Hybrid PQ is not the one that makes that true — see below.
How cipher chaining works under the hood
Your password derives a master key via Argon2id. That master key is expanded through HKDF into two independent 256-bit subkeys — one for AES-256-GCM, one for ChaCha20-Poly1305. Your data is encrypted with AES first, then the AES ciphertext is encrypted again with ChaCha. An attacker must break both algorithms to recover your data.
How hybrid post-quantum works under the hood
Password ──> Argon2id ──> password_key (32 bytes)
|
ML-KEM-768 encapsulate ──> kem_shared_secret (32 bytes)
|
HKDF(password_key || kem_shared_secret) ──> final_key
|
AES-256-GCM
The encryption key is derived from both your password and a lattice-based shared secret. An attacker must break Argon2id (brute-force your password) and ML-KEM-768 (solve the Learning With Errors problem).
Because the two are combined with an AND, the result is at least as strong as the stronger factor. An attacker who does not hold the ML-KEM secret key cannot get in by guessing the password, however weak it is — which is precisely what this mode buys you over a password alone.
What it does not buy you is quantum resistance, because you already had that: see Why quantum resistance does not depend on this.
This is the part most tools get wrong, so it is worth being exact.
A quantum computer threatens the two families of cryptography very differently:
| Effect of a large quantum computer | Used by MORPHEUS for | |
|---|---|---|
| Symmetric (AES-256, ChaCha20) | Grover's algorithm halves the effective key length. 256-bit becomes ~128-bit, which is still far beyond reach | Encrypting your data |
| Password hashing (Argon2id) | No known quantum shortcut. Memory-hardness is unaffected | Turning your password into a key |
| Classical asymmetric (RSA, X25519) | Shor's algorithm breaks it outright | Nothing. MORPHEUS does not use it |
Because MORPHEUS never relies on RSA or elliptic curves to protect your data, there is nothing in the default path for Shor's algorithm to break. A password and Argon2id and AES-256 is a post-quantum construction, and it always was.
So what is ML-KEM-768 for? It solves a different problem: encrypting to someone else without first sharing a password. Tools that offer this normally do it with X25519 or RSA — which is exactly the part a quantum computer breaks. MORPHEUS uses a lattice KEM instead, so the recipient mode is quantum-resistant too.
Put plainly:
- Just want your data safe from future quantum computers? Use MORPHEUS
normally. You already have it, and you never need
pqcrypto. - Want to send something to a colleague without agreeing a password first?
That is what
--hybrid-pqis for, and it needs the optional package.
The honest summary: post-quantum is the floor here, not the upsell.
Launch with no arguments:
python morpheus.pyThe wizard walks you through six steps using keyboard-only navigation — no mouse required. The left sidebar tracks progress and every step includes contextual hints.
Choose an operation: Encrypt converts plaintext into protected ciphertext,
Decrypt reverses the process. Use Up/Down arrows to select, Enter to
confirm, or Ctrl+E / Ctrl+D to skip directly.
Configure the encryption algorithm and key derivation function. Defaults (AES-256-GCM + Argon2id) are secure for most use cases.
- Cipher: AES-256-GCM (NIST standard, hardware-accelerated) or ChaCha20-Poly1305 (constant-time, software-optimized)
- KDF: Argon2id (memory-hard, resists GPU/ASIC) or Scrypt (widely deployed)
- Chain ciphers: Double encryption with independent keys — hedges against a single-cipher break
- Advanced: Plaintext padding, fixed 64 KiB output, omit filename from envelope
Hybrid post-quantum is not offered here. It needs an ML-KEM keypair and the wizard has no way to hold one, so the step points at the CLI route instead. See Using the CLI.
Use Tab between fields, Enter to open dropdowns, Space to toggle checkboxes.
Provide the data to encrypt or decrypt:
- Text mode: Type or paste directly into the editor. For pasting, focus the
text area and use
Ctrl+Shift+V(terminal paste) - File mode: Enter the full path to the file (e.g.
/home/user/secret.txt)
Use Up/Down to switch between Text and File tabs.
For encryption: choose a strong password (4+ random words recommended). The strength meter updates as you type. You must confirm the password.
For decryption: enter the exact password used during encryption — case and special characters must match.
The Paste button reads from the system clipboard (requires xclip/xsel).
If clipboard is unavailable, use Ctrl+Shift+V to paste directly into the
focused field.
Review your configuration summary. If everything looks correct, press
Execute (Tab to the button, then Enter). Warnings appear if your
password is weak. Use Back or number keys to revisit any step.
The result appears in a read-only text area:
- Copy: Copies to system clipboard (falls back to a temporary file if no clipboard backend is available)
- Save to file: Writes output to a temporary file
- Auto-clear: Clears the output display after 60 seconds (stop with the Stop timer button)
Scope of auto-clear. The countdown belongs to the Output step. It clears the displayed text, and it is not a guarantee about data already copied elsewhere. MORPHEUS does not clear your system clipboard, and leaving the Output step cancels the timer. Use
Ctrl+Lto reset all wizard state.
| Shortcut | Action |
|---|---|
1-6 |
Jump directly to a step (if unlocked) |
← / → |
Previous / next step |
Tab |
Cycle through fields in the current step |
Enter |
Select / confirm focused element |
Space |
Toggle checkboxes |
Esc |
Focus the sidebar (then arrow keys to browse) |
Ctrl+E |
Quick Encrypt (sets mode + advances) |
Ctrl+D |
Quick Decrypt |
Ctrl+L |
Clear all and restart |
Ctrl+Q |
Quit |
F1 |
Show keyboard help overlay |
# Interactive mode (prompts for operation, input, and password)
python morpheus.py -o encrypt
# Encrypt text
python morpheus.py -o encrypt --data "sensitive text"
# Encrypt with chaining + Scrypt
python morpheus.py -o encrypt --data "text" --chain --kdf Scrypt
# Encrypt a file (any type: text, binary, images, archives)
python morpheus.py -o encrypt -f document.pdf
# -> morpheus_ab12cd34ef56.enc (random name: the filename is not leaked on disk)
# Decrypt a file (the real name is restored from inside the ciphertext)
python morpheus.py -o decrypt -f morpheus_ab12cd34ef56.enc
# -> document.pdf
# Pipe from stdin
echo "secret" | python morpheus.py -o encrypt --data -
# Generate ML-KEM-768 keypair for hybrid PQ.
# Public key goes to stdout; secret key to a 0600 file (POSIX; on Windows see SECURITY.md).
python morpheus.py --generate-keypair --output my_pq_secret.key
# Hybrid PQ encrypt
python morpheus.py -o encrypt --data "text" \
--hybrid-pq --pq-public-key <base64-pk>
# Hybrid PQ decrypt
python morpheus.py -o decrypt --data "AgEB..." \
--hybrid-pq --pq-secret-key-file my_pq_secret.key
# Use passphrase mode (no digits/specials required)
python morpheus.py -o encrypt --data "text" --passphrase
# Check password against breach databases before encrypting
python morpheus.py -o encrypt --data "text" --check-leaks
# Save your preferred settings for future sessions
python morpheus.py --save-config --cipher ChaCha20-Poly1305 --chain --pad
# Inspect a ciphertext without decrypting (no password needed)
python morpheus.py --inspect --data "AwEB..."
python morpheus.py --inspect -f secret.encPasswords are always entered interactively — never passed as arguments —
to prevent leaking via ps, shell history, or /proc.
All CLI flags
| Flag | Description |
|---|---|
-o, --operation |
encrypt or decrypt |
-d, --data |
Text to encrypt/decrypt. Use - for stdin |
-f, --file |
File to encrypt/decrypt |
--output |
Explicit output path (overrides defaults) |
--cipher |
AES-256-GCM (default) or ChaCha20-Poly1305 |
--kdf |
Argon2id (default) or Scrypt |
--chain |
Enable cipher chaining |
--pad |
Pad plaintext to hide exact length (bucket mode: 256B/1K/4K/16K/64K) |
--fixed-size |
Pad all ciphertexts to 64 KiB (constant-size, max privacy). Implies --pad |
--force |
Overwrite existing output files |
--no-strength-check |
Skip password strength validation |
--no-filename |
Omit original filename from encrypted envelope |
--hybrid-pq |
Enable hybrid post-quantum |
--pq-public-key |
Base64 ML-KEM-768 public key |
--pq-secret-key |
Base64 ML-KEM-768 secret key. Discouraged: argv is readable by other local users |
--pq-secret-key-file |
Path to a file holding the base64 secret key. Preferred over --pq-secret-key |
--generate-keypair |
Generate an ML-KEM-768 keypair: public key to stdout, secret key to a 0600 file (POSIX only; on Windows the mode is not applied — see SECURITY.md) |
--passphrase |
Use passphrase-mode strength check (word-based, no digit/special requirement). Requires 4+ words and 20+ chars |
--check-leaks |
Check password against Have I Been Pwned breach database (k-anonymity, only 5 chars of SHA-1 sent). Requires network |
--save-config |
Save current cipher/KDF/flag preferences to ~/.morpheus/config.toml for future sessions |
--inspect |
Inspect a ciphertext header without decrypting (no password needed). Shows format, cipher, KDF, flags, sizes |
--benchmark |
Benchmark cipher and KDF performance, recommend optimal config |
--dice-entropy N |
Report how much entropy N fair dice rolls carry, and how many more reach 128 or 256 bits. Takes a count, never the rolls. Exits 1 below 128 bits |
--dice-sides N |
Faces on the die used with --dice-entropy (default 6; use 2 for coin flips) |
--version |
Print the version and exit. Quote this when reporting an issue |
Passing any flag runs the CLI. Running python morpheus.py with no arguments launches the GUI.
On 99 vs 100 dice rolls. A fair d6 carries log₂(6) ≈ 2.585 bits, so 99 rolls give 255.9 bits — not the 256 that guidance elsewhere rounds it to.
--dice-entropyreports the measured figure and names the 0.1-bit gap rather than rounding into agreement. The difference has no practical consequence, but if you are following a procedure that says "at least 99 rolls", one more roll costs seconds and lands you cleanly above 256 instead of a hair under it.
Rolls (d6) Entropy 49 126.7 bits below the floor 50 129.2 bits clears 128 99 255.9 bits just short of 256 100 258.5 bits clears 256
| Threat | Protection |
|---|---|
| Offline password brute-force | Argon2id, 64 MiB memory-hard per guess (t=3, p=4). See the note below on cost |
| Future quantum computers | The default path already covers this. Argon2id has no known quantum shortcut, and AES-256 / ChaCha20 retain ~128-bit security against Grover. Optional ML-KEM-768 (FIPS 203) adds a second, asymmetric factor — see below |
| Single-algorithm compromise | Cipher chaining (two independent algorithms, independent keys) |
| Memory forensics | Best-effort ctypes.memset zeroing of key buffers after use. See limitations |
| Ciphertext tampering | AEAD authentication tag (16 bytes) |
| Algorithm downgrade | Header authenticated as AAD (v4 also binds salt and KEM ciphertext) |
| Ciphertext opening to two plaintexts | v4 32-byte key commitment (~128-bit committing security) |
On brute-force cost. The defence is memory-hardness, not wall-clock time. Each guess costs 64 MiB, which is what constrains large-scale parallel attack on GPUs and ASICs. Do not assume a fixed seconds-per-guess figure: on a 2024-class laptop a single derivation takes roughly 30 ms, so a strong password remains essential. Raise
time_costif your threat model needs a higher per-guess cost.
| Limitation | Why |
|---|---|
| Compromised endpoint (malware, keylogger) | No user-space tool can defend against a hostile OS |
Python str immutability |
Password briefly exists as an immutable string before bytearray conversion; GC timing is unpredictable |
| Immutable copies inside crypto bindings | secure_zero clears our own bytearray buffers, but OpenSSL and the argon2 bindings receive immutable bytes copies that cannot be zeroed |
| Swap to disk | Key buffers are not mlocked. On a machine under memory pressure they may be paged to swap. Use full-disk encryption |
| Clipboard contents | MORPHEUS does not clear or restore your system clipboard. Anything you copy stays there until you or another application overwrites it, and history managers (Klipper, macOS Universal Clipboard) may retain copies |
| Setting | Value | Rationale |
|---|---|---|
| Argon2id | t=3, m=64 MiB, p=4 |
OWASP 2024 minimum. Memory-hard, resists GPU/ASIC. The id variant resists both side-channel and brute-force |
| AES-256-GCM | 256-bit key, 96-bit nonce | NIST standard, AES-NI accelerated. 256-bit key gives ~128-bit post-quantum margin via Grover |
| ChaCha20-Poly1305 | 256-bit key, 96-bit nonce | Constant-time in software, preferred without AES-NI. Same quantum margin |
| ML-KEM-768 | FIPS 203, Category 3 | Balances post-quantum security (~AES-192) with practical key sizes. Category 5 doubles sizes for marginal gain |
| Scrypt | n=2^17, r=8, p=1 |
RFC 7914, ~128 MiB. Offered where Argon2 is unavailable |
| Salt | 16 bytes | Standard for Argon2id/Scrypt. Prevents rainbow tables |
| Nonce | 12 bytes | Standard for AES-GCM and ChaCha20. Random nonces safe for expected use |
Be precise about this rather than claiming a blanket guarantee.
| Path | Writes to disk? |
|---|---|
CLI text mode (--data) |
No. Input comes from argv or stdin, output goes to stdout |
CLI file mode (--file) |
Yes, by design. Encrypt writes morpheus_<random>.enc, so the original filename is not exposed on disk; decrypt restores the real name from inside the ciphertext. --output overrides both |
| TUI text mode | Only if you press Save to file, or if Copy finds no clipboard backend and falls back to a temporary file |
--save-config |
Yes. Writes ~/.morpheus/config.toml (mode 0600 on POSIX; not applied on Windows — see SECURITY.md) |
| Anything else | No temporary plaintext files are created |
Output files inherit your umask. On a shared machine, set a restrictive umask before decrypting sensitive files.
The format is self-describing — the header tells the decryptor exactly what algorithms were used. No out-of-band configuration needed.
Same 18-byte header as v3, with the version byte set to 0x04. Three
differences, all in what is bound and how widely:
| v3 | v4 | |
|---|---|---|
| Key commitment | 8-byte truncated HMAC (~32-bit committing security) | 32-byte CTX-shaped hash (~128-bit) |
| Commitment covers | the first key only | all key material (both subkeys when chained) |
| AAD covers | the 18-byte header | header + salt + length-prefixed KEM ciphertext |
| Hybrid combiner | HKDF(salt, pw_key ‖ ss, "hybrid-pq-v1") |
binds the KEM ciphertext, encapsulation key and AAD per NIST SP 800-227 §4.6.3 |
v4 payload: [salt][nonce(s)][KEM prefix if hybrid][32B commitment][ciphertext + tag(s)]
The encapsulation key costs no wire bytes — ML-KEM-768 embeds it in the secret key, so the decryptor recovers it locally.
One limitation v4 does not remove: tampering with the salt or the KEM ciphertext is detected but still reports as a wrong password, because changing either changes the derived key. See SECURITY.md.
Offset Size Field
------ ---- ----------------------------------
0 1 Version (0x03)
1 1 Cipher ID (0x01=AES-256-GCM, 0x02=ChaCha20, 0x03=Chained)
2 1 KDF ID (0x01=Scrypt, 0x02=Argon2id)
3 1 Flags (bit 0=chained, bit 1=hybrid PQ, bit 2=padded)
4-5 2 Reserved (0x0000, validated on read)
6-9 4 KDF param 1 (Argon2: time_cost, Scrypt: n)
10-13 4 KDF param 2 (Argon2: memory_cost, Scrypt: r)
14-17 4 KDF param 3 (Argon2: parallelism, Scrypt: p)
18+ var Payload
v3 stores KDF parameters in the header, enabling decryption without matching the original pipeline config. It also includes an 8-byte key-check value in the payload for clear "wrong password" diagnostics.
v3 payload: [salt][nonce(s)][KEM prefix if hybrid][8B key-check][ciphertext + tag(s)]
Offset Size Field
------ ---- ----------------------------------
0 1 Version (0x02)
1 1 Cipher ID
2 1 KDF ID
3 1 Flags (bit 0=chained, bit 1=hybrid PQ)
4-5 2 Reserved (0x0000)
6+ var Payload
v2 payload: [salt][nonce(s)][KEM prefix if hybrid][ciphertext + tag(s)]
All header bytes are authenticated as AAD — modifying any byte causes decryption to fail, preventing algorithm-downgrade attacks.
pip install pytest
python -m pytest tests/ -v429 tests across 13 test files:
| File | Scope |
|---|---|
test_ciphers.py |
AES-GCM + ChaCha20 roundtrips, NIST SP 800-38D TC14 vector, RFC 8439 vector, indistinguishability, wrong key/AAD/tampered data |
test_kdf.py |
Argon2id + Scrypt derivation, determinism, bytearray returns, salt generation |
test_formats.py |
Serialize/deserialize, flag combinations, version/reserved byte validation, AAD collision resistance |
test_pipeline.py |
All mode roundtrips (single/chained/hybrid/both), wrong password (InvalidTag), cross-compatibility, payload truncation, KEM length=0 bypass, header tampering |
test_memory.py |
secure_zero, SecureBuffer, secure_key context manager |
test_validation.py |
Password scoring (0-100), minimum requirements, edge cases |
test_config.py |
Preference load/save, allow-list validation, file mode |
test_fuzz.py |
Property-based fuzzing of the parser against hostile input (requires hypothesis) |
test_cli.py |
File encrypt/decrypt roundtrip (text + binary), path traversal prevention |
test_gui.py |
Wizard mount, step transitions, shortcuts, encrypt/decrypt roundtrip, clipboard fallbacks |
test_wizard_state.py |
State validation per step, step unlocking rules, edge cases |
test_theme.py |
Palette contrast against the background, accent and low-contrast token restrictions parsed out of the stylesheet, and the rendered colour set pinned against an exported screenshot |
Tests include NIST SP 800-38D and RFC 8439 reference vectors verified
against the cryptography library's validated implementations.
Morpheus/
├── morpheus_crypt/
│ ├── __init__.py # Package version
│ ├── __main__.py # Entry point (auto-detects GUI vs CLI)
│ ├── gui.py # Thin shim → ui/app.py
│ ├── cli.py # CLI with file encryption support
│ ├── ui/ # Wizard GUI (Textual)
│ │ ├── app.py # MorpheusWizard — 2-pane shell, navigation, workers
│ │ ├── theme.py # Colour tokens + CSS
│ │ ├── state.py # WizardState dataclass + per-step validation
│ │ ├── sidebar.py # Left pane step list (✓/▸/dim)
│ │ └── steps/
│ │ ├── mode.py # Step 1 — Encrypt / Decrypt
│ │ ├── settings.py # Step 2 — Cipher, KDF, options
│ │ ├── input.py # Step 3 — Text editor / file path
│ │ ├── password.py # Step 4 — Password + strength + paste
│ │ ├── review.py # Step 5 — Summary + Run
│ │ └── output.py # Step 6 — Result + copy + countdown
│ └── core/
│ ├── ciphers.py # AES-256-GCM, ChaCha20-Poly1305
│ ├── kdf.py # Argon2id, Scrypt
│ ├── pipeline.py # Orchestration: chaining, hybrid PQ, key lifecycle
│ ├── formats.py # Versioned binary format with AAD
│ ├── config.py # Persistent user preferences (~/.morpheus/config.toml)
│ ├── memory.py # ctypes.memset zeroing of key buffers
│ └── validation.py # Password scoring, passphrase mode, breach detection
├── tests/ # 429 tests (NIST/RFC vectors included)
├── docs/USAGE.md # Full guide for technical and non-technical readers
├── SECURITY.md # Vulnerability disclosure policy
├── CHANGELOG.md # Version history
├── CONTRIBUTING.md # Contributor guide
├── .github/workflows/ci.yml # CI: Python 3.10-3.13 test matrix
├── pyproject.toml
├── requirements.txt
└── LICENSE # MIT
| Package | Purpose | Required |
|---|---|---|
cryptography |
AES-GCM, ChaCha20, Scrypt, HKDF | Yes |
argon2-cffi |
Argon2id key derivation | Yes |
textual |
Terminal GUI framework | Yes |
pyperclip |
Clipboard access (Linux: requires xclip or xsel) |
Yes |
pqcrypto |
ML-KEM-768 post-quantum KEM (community wrapper around PQClean, not FIPS-validated, no public audit) | Optional |
Python 3.10+
Terminal size: the GUI needs at least 100x30. Below that it shows a "terminal too small" screen rather than a clipped wizard, and resizing back up restores your place and any finished result. The CLI has no size requirement.
Linux clipboard: Install
xcliporxselfor clipboard support:sudo apt install xclip
See CONTRIBUTING.md for guidelines. We welcome:
- Bug reports and security disclosures (see SECURITY.md)
- New cipher or KDF implementations
- Documentation improvements
- Test coverage expansion
MORPHEUS is provided as-is for educational and personal use. It has not undergone formal FIPS 140-3 validation or independent third-party audit. Do not rely on it as your sole protection for data subject to legal, regulatory, or compliance requirements (HIPAA, GDPR, PCI-DSS, etc.).
The authors are not responsible for data loss, unauthorized disclosure, or any damages resulting from the use of this software. There is no password recovery mechanism — if you forget your password, your data is permanently and irrecoverably lost.
Use of cryptographic software may be restricted or regulated in some jurisdictions. You are responsible for compliance with all applicable laws.
- No telemetry or analytics: MORPHEUS does not phone home or collect usage
data. The only network connection is opt-in breach checking (
--check-leaks), which uses k-anonymity and never sends your actual password. - Disk usage is narrow but not zero: CLI text mode is entirely in-memory.
File mode writes only the ciphertext (or the decrypted original). The TUI
writes a temporary file if you press Save to file, or if Copy finds no
clipboard backend.
--save-configwrites~/.morpheus/config.toml. See What Touches the Disk. - Clipboard is not managed: MORPHEUS does not clear or restore your system clipboard. Anything you copy stays there until something else overwrites it.
- Plaintext length: Without
--pad, ciphertext length reveals approximate plaintext length. Use--padfor length-hiding (pads to buckets: 256B, 1K, 4K, 16K, 64K). Bucket membership is still visible. - Ciphertext is identifiable: The versioned header (0x02/0x03) makes MORPHEUS ciphertexts recognizable. This tool does not provide plausible deniability or steganography — it is designed for confidentiality, not undetectability.
- Password as signal: A strong password (high entropy) may itself signal security awareness to an observer. This is inherent to password-based encryption.