{"id":36985594,"url":"https://github.com/matutetandil/anyhide","last_synced_at":"2026-01-13T23:02:41.715Z","repository":{"id":328819411,"uuid":"1116378380","full_name":"matutetandil/anyhide","owner":"matutetandil","description":"Hide any data in any file. Steganography tool that never modifies the carrier - transmits only encrypted positions. X25519 + ChaCha20 with forward secrecy.","archived":false,"fork":false,"pushed_at":"2025-12-19T18:32:44.000Z","size":811,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T19:46:47.313Z","etag":null,"topics":["chacha20","cli","covert-communication","cryptography","data-hiding","encryption","forward-secrecy","plausible-deniability","privacy","rust","security","steganography","x25519"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matutetandil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-14T18:35:50.000Z","updated_at":"2025-12-24T13:53:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/matutetandil/anyhide","commit_stats":null,"previous_names":["matutetandil/anyhide"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/matutetandil/anyhide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matutetandil%2Fanyhide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matutetandil%2Fanyhide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matutetandil%2Fanyhide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matutetandil%2Fanyhide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matutetandil","download_url":"https://codeload.github.com/matutetandil/anyhide/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matutetandil%2Fanyhide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28405148,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T21:51:37.118Z","status":"ssl_error","status_checked_at":"2026-01-13T21:45:14.585Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chacha20","cli","covert-communication","cryptography","data-hiding","encryption","forward-secrecy","plausible-deniability","privacy","rust","security","steganography","x25519"],"created_at":"2026-01-13T23:02:41.034Z","updated_at":"2026-01-13T23:02:41.709Z","avatar_url":"https://github.com/matutetandil.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anyhide - Hide Anything in Anything\n\n[![Crates.io](https://img.shields.io/crates/v/anyhide.svg)](https://crates.io/crates/anyhide)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Rust](https://img.shields.io/badge/rust-1.70%2B-blue.svg)](https://www.rust-lang.org)\n[![GitHub Release](https://img.shields.io/github/v/release/matutetandil/anyhide)](https://github.com/matutetandil/anyhide/releases)\n\n**Hide anything inside anything.** Anyhide is an advanced steganography and encryption tool that conceals any data (text, files, binaries) within any carrier file(s) (images, videos, documents, executables) using hybrid encryption with forward secrecy and plausible deniability.\n\n## Why Anyhide?\n\nTraditional steganography modifies the carrier file and transmits it. Anyhide is different:\n\n| Traditional Steganography | Anyhide |\n|---------------------------|---------|\n| Modifies the carrier file | Never touches the carrier |\n| Transmits the modified file | Transmits only a short code |\n| Carrier can be analyzed | Carrier stays untouched |\n| Hide text in images | Hide **anything** in **anything** |\n\n**Use cases:**\n- Hide encrypted files inside a shared video\n- Conceal sensitive documents using a public PDF as carrier\n- Store secrets referenced by any file both parties have\n- Covert communication with plausible deniability\n\n## How It Works\n\nAnyhide uses a **pre-shared carrier** model:\n\n1. Both parties have the same file (ANY file: image, video, PDF, text, etc.)\n2. Sender hides data by finding byte patterns in the carrier\n3. Only an encrypted code is transmitted - **the carrier is never sent**\n4. Receiver uses the same carrier + code to extract the hidden data\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  SENDER                         RECEIVER                    │\n│                                                             │\n│  carrier.mp4 ──┐                      ┌── carrier.mp4       │\n│                │                      │   (same file)       │\n│  secret.zip ───┼──► ANYHIDE CODE ─────┼──► secret.zip       │\n│                │   (only this         │                     │\n│  passphrase ───┘    is sent)          └── passphrase        │\n│                                                             │\n│  The carrier is NEVER transmitted                           │\n└─────────────────────────────────────────────────────────────┘\n```\n\n## Key Features\n\n- **Any carrier**: text, images, audio, video, PDFs, executables, archives\n- **Any payload**: text messages, binary files, documents, archives\n- **Dual-layer encryption**: Symmetric (ChaCha20) + Asymmetric (X25519)\n- **Forward secrecy ratchet**: Key rotation per message - past messages stay secure even if keys leak\n- **Ephemeral keys**: Generate rotating keys for perfect forward secrecy\n- **Key fingerprints**: Verify keys out-of-band (hex, emoji, visual art)\n- **Mnemonic backup**: Export/import keys as 24-word BIP39 phrases for paper backup\n- **Contacts with aliases**: Save contacts in `~/.anyhide/contacts.toml`, use `--to alice`\n- **P2P Chat over Tor**: Real-time encrypted chat via Tor hidden services (experimental)\n- **Duress password**: Two messages, two passphrases - reveal the decoy under coercion\n- **Message signing**: Ed25519 signatures for sender authentication\n- **Message expiration**: Auto-expiring messages\n- **Code splitting**: Split codes for multi-channel delivery\n- **QR code support**: Share codes via QR\n- **Plausible deniability**: Wrong passphrase returns garbage, not an error\n- **Never fails**: Decoder always returns something - prevents brute-force detection\n- **Library support**: Use Anyhide in your own Rust projects\n\n## Installation\n\n### From crates.io\n\n```bash\ncargo install anyhide\n```\n\n### Download Pre-built Binary\n\nDownload from [GitHub Releases](https://github.com/matutetandil/anyhide/releases):\n\n- **Linux**: `anyhide-linux-x86_64` or `anyhide-linux-aarch64`\n- **macOS**: `anyhide-macos-x86_64` (Intel) or `anyhide-macos-aarch64` (Apple Silicon)\n- **Windows**: `anyhide-windows-x86_64.exe`\n\n### Build from Source\n\n```bash\ngit clone https://github.com/matutetandil/anyhide.git\ncd anyhide\ncargo build --release\n```\n\n## Quick Start\n\n### 1. Generate Keys\n\n```bash\nanyhide keygen -o mykeys\n# Creates: mykeys.pub, mykeys.key, mykeys.sign.pub, mykeys.sign.key\n```\n\n### 2. Encode a Message\n\n```bash\n# Using any text file as carrier\necho \"The amazing Amanda went to the park yesterday\" \u003e carrier.txt\n\nanyhide encode \\\n  -c carrier.txt \\\n  -m \"ama park\" \\\n  -p \"secret123\" \\\n  --their-key recipient.pub\n# Output: AwNhYmNkZWZn... (send this code)\n```\n\n### 3. Decode a Message\n\n```bash\nanyhide decode \\\n  --code \"AwNhYmNkZWZn...\" \\\n  -c carrier.txt \\\n  -p \"secret123\" \\\n  --my-key recipient.key\n# Output: ama park\n```\n\n## Command Reference\n\n### Generate Keys\n\n```bash\nanyhide keygen [OPTIONS] -o \u003cname\u003e\n\nOptions:\n  -o, --output \u003cPATH\u003e      Output path for keys (default: anyhide)\n  --ephemeral              Generate ephemeral keys for forward secrecy\n  --show-mnemonic          Show 24-word backup phrases (long-term keys only)\n  --contact \u003cNAME\u003e         Contact name (required for consolidated storage)\n  --eph-keys \u003cPATH\u003e        Path to .eph.key file (consolidated private keys)\n  --eph-pubs \u003cPATH\u003e        Path to .eph.pub file (consolidated public keys)\n  --eph-file \u003cPATH\u003e        Path to .eph file (unified storage)\n\n# Long-term keys (default)\nanyhide keygen -o mykeys\n\n# Long-term keys with mnemonic backup phrases\nanyhide keygen -o mykeys --show-mnemonic\n# Shows 24-word phrases for both encryption and signing keys\n# Creates: mykeys.pub, mykeys.key, mykeys.sign.pub, mykeys.sign.key\n\n# Ephemeral keys (individual files)\nanyhide keygen -o alice --ephemeral\n# Creates: alice.pub, alice.key (with EPHEMERAL PEM headers)\n\n# Ephemeral keys (consolidated separate files)\nanyhide keygen --ephemeral --eph-keys keys.eph.key --eph-pubs keys.eph.pub --contact bob\n# Adds/updates contact \"bob\" in both JSON files\n\n# Ephemeral keys (unified file)\nanyhide keygen --ephemeral --eph-file contacts.eph --contact bob\n# Adds/updates contact \"bob\" with my_private and placeholder their_public\n```\n\n### Encode\n\n```bash\nanyhide encode [OPTIONS] -c \u003cCARRIER\u003e... -p \u003cPASSPHRASE\u003e\n\nOptions:\n  -c, --carriers \u003cPATH\u003e... Carrier file(s) - multiple files are concatenated.\n                           Order matters! Wrong order = garbage (N! combinations)\n  -m, --message \u003cTEXT\u003e     Text message (or use --file for binary)\n  -f, --file \u003cPATH\u003e        Binary file to hide\n  -p, --passphrase \u003cPASS\u003e  Passphrase for encryption\n\nKey options (choose one):\n  --their-key \u003cPATH\u003e       Recipient's public key (.pub file)\n  --to \u003cALIAS\u003e             Contact alias (from ~/.anyhide/contacts.toml)\n  --eph-file \u003cPATH\u003e        Unified ephemeral key store (.eph)\n  --eph-keys \u003cPATH\u003e        Separated ephemeral private keys (.eph.key)\n  --eph-pubs \u003cPATH\u003e        Separated ephemeral public keys (.eph.pub)\n  --contact \u003cNAME\u003e         Contact name (required with --eph-file or --eph-keys/--eph-pubs)\n  -k, --key \u003cPATH\u003e         [DEPRECATED] Use --their-key instead\n\nRatchet options:\n  --ratchet                Enable forward secrecy (auto key rotation)\n  --my-key \u003cPATH\u003e          Your private key (for auto-saving next keypair)\n\nDuress password (plausible deniability):\n  --decoy \u003cMESSAGE\u003e        Decoy message revealed with --decoy-pass\n  --decoy-pass \u003cPASS\u003e      Passphrase for the decoy message\n\nOther options:\n  --sign \u003cPATH\u003e            Sign with Ed25519 key\n  --expires \u003cTIME\u003e         Expiration: \"+30m\", \"+24h\", \"+7d\", \"2025-12-31\"\n  --split \u003cN\u003e              Split into N parts (2-10)\n  --qr \u003cPATH\u003e              Generate QR code\n  --qr-format \u003cFMT\u003e        QR format: png, svg, ascii\n  --min-coverage \u003c0-100\u003e   Minimum carrier coverage (default: 100)\n  -v, --verbose            Show details\n```\n\n### Decode\n\n```bash\nanyhide decode [OPTIONS] -c \u003cCARRIER\u003e... -p \u003cPASSPHRASE\u003e\n\nCode input (choose one):\n  --code \u003cTEXT\u003e            Direct base64 code\n  --code-qr \u003cPATH\u003e         Read from QR image\n  --code-file \u003cPATH\u003e       Read from text file\n  --parts \u003cFILES\u003e...       Combine split parts (2-10 files)\n\nOptions:\n  -c, --carriers \u003cPATH\u003e... Carrier file(s) - EXACT same files in EXACT same order!\n  -p, --passphrase \u003cPASS\u003e  Passphrase for decryption\n\nKey options (choose one):\n  --my-key \u003cPATH\u003e          Your private key (.key file)\n  --eph-file \u003cPATH\u003e        Unified ephemeral key store (.eph)\n  --eph-keys \u003cPATH\u003e        Separated ephemeral private keys (.eph.key)\n  --eph-pubs \u003cPATH\u003e        Separated ephemeral public keys (.eph.pub)\n  --contact \u003cNAME\u003e         Contact name (required with --eph-file or --eph-keys/--eph-pubs)\n  -k, --key \u003cPATH\u003e         [DEPRECATED] Use --my-key instead\n\nRatchet options:\n  --their-key \u003cPATH\u003e       Sender's public key (for auto-saving their next key)\n\nOther options:\n  --verify \u003cPATH\u003e          Verify signature with sender's public key\n  -o, --output \u003cPATH\u003e      Output file (required for binary)\n  -v, --verbose            Show details\n```\n\n### Fingerprint\n\nDisplay a key's fingerprint for out-of-band verification (like Signal/WhatsApp).\n\n```bash\nanyhide fingerprint \u003cKEY_PATH\u003e [OPTIONS]\n\nOptions:\n  -f, --format \u003cFMT\u003e     Output format: hex, emoji, art, or all (default: all)\n\n# Show all fingerprint formats\nanyhide fingerprint alice.pub\n\n# Show only emoji fingerprint (easy to compare by phone)\nanyhide fingerprint alice.pub -f emoji\n```\n\nOutput example:\n```\nKey: alice.pub\n\nHex Fingerprint:\n  75EC37D4 51EBEDE4 E4AA4182 FD719560\n  BE3E765C CE49A772 597A0ACF 09AC05FA\n\nEmoji Fingerprint:\n  🌲 🚂 🌺 🦊 🐺 ⛵ 🏎️ 🎻\n\nVisual Fingerprint:\n  +-----------------+\n  |             o .o|\n  |           .o ..+|\n  |          . o..oo|\n  |         + o .o..|\n  |        S + +.+oB|\n  |         . *.+o#+|\n  |        .   O+=+B|\n  |         . o.Oo= |\n  |          E ..*  |\n  +-----------------+\n```\n\n### Mnemonic Backup\n\nExport and import long-term keys as 24-word BIP39 phrases for paper backup.\n\n```bash\n# Export existing key to mnemonic\nanyhide export-mnemonic mykeys.key\n# Shows 24 words for paper backup\n\n# Export signing key\nanyhide export-mnemonic mykeys.sign.key\n\n# Import encryption key from mnemonic (interactive)\nanyhide import-mnemonic -o restored\n# Enter 24 words when prompted\n# Creates: restored.key, restored.pub\n\n# Import signing key from mnemonic\nanyhide import-mnemonic -o restored --key-type signing\n# Creates: restored.sign.key, restored.sign.pub\n```\n\n**Important:** Mnemonic backup is only for long-term private keys (`.key`, `.sign.key`). Ephemeral keys rotate per message and should not be backed up.\n\n### Contacts\n\nManage contacts with aliases to avoid typing full paths.\n\n```bash\n# Add a contact\nanyhide contacts add alice /path/to/alice.pub\nanyhide contacts add alice /path/to/alice.pub --signing-key /path/to/alice.sign.pub\n\n# List all contacts\nanyhide contacts list\n\n# Show contact details with fingerprint\nanyhide contacts show alice\n\n# Remove a contact\nanyhide contacts remove alice\n\n# Use contact in encode\nanyhide encode -c carrier.txt -m \"Hello\" -p \"pass\" --to alice\n```\n\nContacts are stored in `~/.anyhide/contacts.toml`:\n```toml\n[contacts.alice]\npublic_key = \"/path/to/alice.pub\"\nsigning_key = \"/path/to/alice.sign.pub\"\n\n[contacts.bob]\npublic_key = \"/path/to/bob.pub\"\n```\n\n### P2P Chat over Tor\n\nReal-time encrypted chat using Tor hidden services. Both peers are equal - no server/client distinction.\n\n**Security Warning:** Arti's onion services are experimental and not as secure as C-Tor. Do not use for highly sensitive communications.\n\n**Setup (one time):**\n```bash\n# 1. Generate your keys (encryption + signing)\nanyhide keygen -o mykeys\nanyhide keygen -o mykeys --signing\n\n# 2. Initialize your chat identity (bootstraps Tor, shows your .onion)\nanyhide chat init -k mykeys -s mykeys.sign\n# Output: Your .onion address: xyz123abc.onion\n\n# 3. Add a contact (you need their .onion address and public keys)\nanyhide chat add bob \u003cbob.onion\u003e --key bob.pub --sign-key bob.sign.pub\n```\n\n**Start chatting:**\n```bash\nanyhide chat bob\n# Enter your passphrase when prompted (input is hidden)\n```\n\n**Pre-shared carriers (optional, extra security):**\n```bash\n# Both parties must use the SAME files in the SAME order\nanyhide chat bob -c photo.jpg -c song.mp3 -c document.pdf\n\n# The carrier files are NEVER transmitted - only a hash is verified\n# This provides extra security: the files become an additional secret\n# N files = N! additional security (3 files = 6 possible orders)\n```\n\nThat's it! The system will:\n1. Ask for your passphrase (required for encryption, input is hidden)\n2. Create your hidden service\n3. Try to connect to Bob's .onion address\n4. If Bob isn't online, wait for him to connect to you\n5. First successful connection (incoming or outgoing) establishes the session\n6. Launch the TUI (Terminal User Interface)\n\n**TUI Interface:**\n```\n┌─ Anyhide Chat - bob ─────────────────────────────────┐\n│ Connected | abc123...onion | 2↑ 1↓                   │\n├──────────────────────────────────────────────────────┤\n│                                                      │\n│  [14:32] Connected to bob                            │\n│  [14:32] Type /help for commands. Ctrl+C to quit.    │\n│  [14:33] you: Hello Bob!                             │\n│  [14:33] bob: Hey Alice! How are you?                │\n│                                                      │\n├─ Input ──────────────────────────────────────────────┤\n│ \u003e your message here...                  11/256       │\n└──────────────────────────────────────────────────────┘\n```\n\nThe counter shows `current/max` characters. Turns yellow at \u003c20 remaining, red at 0.\n\n**Chat management commands:**\n```bash\nanyhide chat init -k \u003ckeys\u003e -s \u003csign\u003e   # Initialize your identity (shows .onion)\nanyhide chat add \u003cname\u003e \u003conion\u003e ...     # Add a contact\nanyhide chat list                       # List contacts\nanyhide chat show \u003cname\u003e                # Show contact details\nanyhide chat show me                    # Show your own identity and .onion\nanyhide chat remove \u003cname\u003e              # Remove a contact\nanyhide chat export-qr -o me.png        # Export your identity as QR code\nanyhide chat import-qr me.png -n alice  # Import contact from QR code\n```\n\n**Local testing with profiles:**\n```bash\n# Run multiple identities on the same machine (for testing)\n# Terminal 1:\nanyhide chat --profile alice init -k alice -s alice.sign\nanyhide chat --profile alice add bob \u003cbob.onion\u003e --key bob.pub --sign-key bob.sign.pub\nanyhide chat --profile alice bob\n\n# Terminal 2:\nanyhide chat --profile bob init -k bob -s bob.sign\nanyhide chat --profile bob add alice \u003calice.onion\u003e --key alice.pub --sign-key alice.sign.pub\nanyhide chat --profile bob alice\n```\n\nEach profile gets separate config and Tor state directories.\n\n**Chat session commands:**\n- `/quit` or `/q` - Exit the chat\n- `/status` or `/s` - Show session statistics\n- `/help` or `/h` - Show available commands\n- `/clear` or `/c` - Clear message history\n\n**Keyboard shortcuts:**\n- `Ctrl+C` or `Esc` - Quit\n- `Enter` - Send message\n- `Page Up/Down` - Scroll message history\n- `Ctrl+Up/Down` - Scroll one line\n\n**How it works:**\n1. Both parties initialize with `chat init` (creates their .onion identity)\n2. Exchange identities out-of-band:\n   - **Option A (QR):** `chat export-qr` to generate QR, scan with `chat import-qr`\n   - **Option B (Manual):** Share .onion address and public keys, use `chat add`\n3. Run `anyhide chat \u003ccontact\u003e` - both peers create hidden services and race to connect\n4. First successful connection wins, handshake establishes encrypted session\n5. Messages encrypted with Double Ratchet protocol for forward secrecy\n\n### Other Commands\n\n```bash\nanyhide multi-encrypt    # Encrypt for multiple recipients\nanyhide multi-decrypt    # Decrypt multi-recipient message\nanyhide qr-generate      # Generate QR from code\nanyhide qr-read          # Read code from QR\nanyhide qr-info          # Check QR capacity\nanyhide update           # Update to latest version\n```\n\n## Examples\n\n### Binary Files as Carrier\n\nUse any file (video, PDF, image, executable) as carrier:\n\n```bash\n# Hide text in a shared video\nanyhide encode -c shared_video.mp4 -m \"secret message\" -p \"pass\" -k bob.pub\n\n# Hide a ZIP file inside a PDF\nanyhide encode -c document.pdf --file secret.zip -p \"pass\" -k bob.pub\n\n# Extract hidden file\nanyhide decode --code \"...\" -c document.pdf -p \"pass\" -k bob.key -o secret.zip\n```\n\n### Message Signing\n\n```bash\n# Sign message\nanyhide encode -c carrier.txt -m \"From Alice\" -p \"pass\" -k bob.pub --sign alice.sign.key\n\n# Verify signature\nanyhide decode --code \"...\" -c carrier.txt -p \"pass\" -k bob.key --verify alice.sign.pub\n# Output: From Alice\n# Signature: VALID\n```\n\n### Message Expiration\n\n```bash\n# Message expires in 24 hours\nanyhide encode -c carrier.txt -m \"Temp info\" -p \"pass\" -k bob.pub --expires \"+24h\"\n\n# After expiration: returns garbage (not an error)\n```\n\n### Code Splitting\n\n```bash\n# Split into 3 parts\nanyhide encode -c carrier.txt -m \"Secret\" -p \"pass\" -k bob.pub --split 3\n# Output: part-1: xxx, part-2: yyy, part-3: zzz\n\n# Decode with all parts in order\nanyhide decode --parts p1.txt p2.txt p3.txt -c carrier.txt -p \"pass\" -k bob.key\n\n# Wrong order = garbage (plausible deniability)\n```\n\n### QR Codes\n\n```bash\n# Generate code + QR in one step\nanyhide encode -c carrier.txt -m \"Secret\" -p \"pass\" -k bob.pub --qr code.png\n\n# Read QR and decode\nanyhide decode --code-qr code.png -c carrier.txt -p \"pass\" -k bob.key\n\n# Split QR codes\nanyhide encode -c carrier.txt -m \"Secret\" -p \"pass\" -k bob.pub --split 3 --qr code.png\n# Creates: code-1.png, code-2.png, code-3.png\n```\n\n### Multi-Carrier Encoding\n\nUse multiple carriers concatenated in order. The order is an additional secret!\n\n```bash\n# Encode with 3 carriers - order matters!\nanyhide encode -c photo.jpg -c song.mp3 -c document.pdf \\\n  -m \"Secret message\" -p \"pass\" --their-key bob.pub\n\n# Decode with EXACT same files in EXACT same order\nanyhide decode -c photo.jpg -c song.mp3 -c document.pdf \\\n  --code \"...\" -p \"pass\" --my-key bob.key\n\n# Wrong order = garbage (plausible deniability)\nanyhide decode -c song.mp3 -c photo.jpg -c document.pdf \\\n  --code \"...\" -p \"pass\" --my-key bob.key\n# Returns garbage, not an error\n```\n\n**Security benefit:** N carriers provide N! additional combinations:\n- 2 carriers = 2 combinations\n- 3 carriers = 6 combinations\n- 4 carriers = 24 combinations\n- 5 carriers = 120 combinations\n\nWhen using multiple carriers:\n- All files are read as bytes and concatenated in order\n- Single text file with `-c file.txt` preserves text carrier behavior\n- Multiple files always become a binary carrier\n\n### Forward Secrecy Ratchet\n\nEnable key rotation per message for perfect forward secrecy.\n\n#### Ephemeral Key Storage Formats\n\nAnyhide supports 3 storage formats for ephemeral keys:\n\n**Option 1: Individual PEM files** (simple, single contact)\n```bash\nanyhide keygen -o alice --ephemeral\n# Creates: alice.pub, alice.key (with EPHEMERAL headers)\n```\n\n**Option 2: Separate consolidated JSON files** (multiple contacts)\n```bash\nanyhide keygen --ephemeral --eph-keys mykeys.eph.key --eph-pubs contacts.eph.pub --contact bob\n# mykeys.eph.key: JSON with your private keys for each contact\n# contacts.eph.pub: JSON with each contact's public key\n```\n\n**Option 3: Unified JSON file** (recommended for chat apps)\n```bash\nanyhide keygen --ephemeral --eph-file contacts.eph --contact bob\n# contacts.eph: JSON with both my_private and their_public per contact\n```\n\n#### Automatic Ratchet with Individual Files\n\n```bash\n# Step 1: Both parties generate ephemeral keys and exchange public keys\nanyhide keygen -o alice --ephemeral   # Alice: alice.pub, alice.key\nanyhide keygen -o bob --ephemeral     # Bob: bob.pub, bob.key\n\n# Step 2: Alice sends message (keys rotate automatically)\nanyhide encode -c carrier.txt -m \"Hello Bob\" -p \"pass\" \\\n    --their-key bob.pub --my-key alice.key --ratchet\n# Output: Just the code (alice.key updated with next keypair)\n\n# Step 3: Bob decodes (their public key updated automatically)\nanyhide decode --code \"...\" -c carrier.txt -p \"pass\" \\\n    --my-key bob.key --their-key alice.pub\n# Output: Hello Bob (alice.pub updated with her next public key)\n\n# Step 4: Bob replies (keys rotate again)\nanyhide encode -c carrier.txt -m \"Hi Alice!\" -p \"pass\" \\\n    --their-key alice.pub --my-key bob.key --ratchet\n# Output: Just the code (bob.key updated)\n```\n\n#### Automatic Ratchet with Separated Stores\n\nFor environments where you want private keys and public keys in separate files:\n\n```bash\n# Step 1: Setup - create separated key stores\nanyhide keygen --ephemeral --eph-keys alice.eph.key --eph-pubs alice.eph.pub --contact bob\nanyhide keygen --ephemeral --eph-keys bob.eph.key --eph-pubs bob.eph.pub --contact alice\n# Exchange initial public keys\n\n# Step 2: Alice sends message\nanyhide encode -c carrier.txt -m \"Hello Bob\" -p \"pass\" \\\n    --eph-keys alice.eph.key --eph-pubs alice.eph.pub --contact bob --ratchet\n# Output: Just the code (alice.eph.key[bob] updated with next keypair)\n\n# Step 3: Bob decodes\nanyhide decode --code \"...\" -c carrier.txt -p \"pass\" \\\n    --eph-keys bob.eph.key --eph-pubs bob.eph.pub --contact alice\n# Output: Hello Bob (bob.eph.pub[alice] updated with Alice's next public key)\n```\n\n#### Automatic Ratchet with Unified Store (Recommended)\n\n```bash\n# Step 1: Setup - create unified key stores for each party\nanyhide keygen --ephemeral --eph-file alice.eph --contact bob\nanyhide keygen --ephemeral --eph-file bob.eph --contact alice\n# Exchange public keys initially\n\n# Step 2: Alice sends message\nanyhide encode -c carrier.txt -m \"Hello Bob\" -p \"pass\" \\\n    --eph-file alice.eph --contact bob --ratchet\n# Output: Just the code (alice.eph[bob].my_private updated)\n\n# Step 3: Bob decodes\nanyhide decode --code \"...\" -c carrier.txt -p \"pass\" \\\n    --eph-file bob.eph --contact alice\n# Output: Hello Bob (bob.eph[alice].their_public updated)\n\n# Step 4: Bob replies\nanyhide encode -c carrier.txt -m \"Hi Alice!\" -p \"pass\" \\\n    --eph-file bob.eph --contact alice --ratchet\n# Output: Just the code (bob.eph[alice].my_private updated)\n```\n\n**Key points:**\n- Messages are always clean - no key information displayed\n- Keys rotate automatically after each encode/decode\n- Use `-v` for verbose output if you need to see key details\n- The `--key` flag is deprecated - use `--my-key` and `--their-key` instead\n\n#### Library Usage for Chat Applications\n\n```rust\nuse anyhide::{encode_with_config, decode_with_config, EncoderConfig, DecoderConfig};\nuse anyhide::{KeyPair, save_unified_keys_for_contact, update_unified_public_key};\n\n// Initial setup: generate keys for Bob\nlet my_keypair = KeyPair::generate_ephemeral();\nsave_unified_keys_for_contact(\n    \"contacts.eph\",\n    \"bob\",\n    my_keypair.secret_key(),\n    \u0026bobs_initial_public_key,\n)?;\n\n// Encode with ratchet enabled\nlet config = EncoderConfig { ratchet: true, ..Default::default() };\nlet result = encode_with_config(\u0026carrier, \"Hello!\", \"pass\", \u0026bobs_public_key, \u0026config)?;\n\n// result.next_keypair contains your NEXT key pair\n// Save it for the next message you send\n// result.code contains the encrypted message\n\n// On receiving a reply, decode and get their next key\nlet decoded = decode_with_config(\u0026code, \u0026carrier, \"pass\", \u0026my_secret_key, \u0026DecoderConfig::default());\nif let Some(next_key_bytes) = decoded.next_public_key {\n    // Update Bob's public key for the next message\n    let next_public = PublicKey::from(\u003c[u8; 32]\u003e::try_from(next_key_bytes)?);\n    update_unified_public_key(\"contacts.eph\", \"bob\", \u0026next_public)?;\n}\n```\n\n**How the ratchet works:**\n1. Each message includes sender's NEXT public key\n2. Recipient uses that key for the reply\n3. Keys rotate with every message exchange\n4. Compromised keys cannot decrypt past messages\n\n## Security Properties\n\n1. **Four-Factor Security**: Carrier + Passphrase + Private Key + Correct Version\n2. **Never-Fail Decoder**: Always produces output - no error signals for attackers\n3. **Plausible Deniability**: Wrong inputs return garbage, not errors\n4. **Forward Secrecy**: Ephemeral keys protect past messages\n5. **Code Splitting**: Wrong order = garbage (no error)\n\n## Disclaimer\n\n**Anyhide is provided for educational and legitimate privacy purposes only.**\n\nThis software is a tool, and like any tool, it can be used for good or bad purposes. The authors:\n- **DO NOT** endorse or encourage any illegal activities\n- **ARE NOT** responsible for how this software is used\n- **PROVIDE** this software \"as is\" without warranty\n\n**You are solely responsible for ensuring your use complies with all applicable laws.**\n\n## Documentation\n\n- **User Manual**: This README\n- **Architecture \u0026 Development**: [ARCHITECTURE.md](ARCHITECTURE.md)\n- **Version History**: [CHANGELOG.md](CHANGELOG.md)\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Version\n\nCurrent version: 0.11.0 (see [CHANGELOG.md](CHANGELOG.md))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatutetandil%2Fanyhide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatutetandil%2Fanyhide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatutetandil%2Fanyhide/lists"}