anyhide 0.10.0

Hide any data in any file - steganography tool with hybrid encryption and plausible deniability
Documentation
# Anyhide - Architecture & Development Guide

This document provides technical documentation for developers working on Anyhide.

## Project Structure

```
anyhide/
├── src/
│   ├── main.rs              # CLI entry point, clap parsing
│   ├── lib.rs               # Public re-exports, version constants
│   │
│   ├── commands/            # CLI command implementations (Strategy pattern)
│   │   ├── mod.rs           # CommandExecutor trait definition
│   │   ├── keygen.rs        # Key pair generation command
│   │   ├── encode.rs        # Message/file encoding command
│   │   ├── decode.rs        # Message/file decoding command
│   │   ├── multi_encrypt.rs # Multi-recipient encryption
│   │   ├── multi_decrypt.rs # Multi-recipient decryption
│   │   ├── qr_generate.rs   # QR code generation
│   │   ├── qr_read.rs       # QR code reading
│   │   ├── qr_info.rs       # QR capacity analysis
│   │   └── update.rs        # Self-update command
│   │
│   ├── crypto/              # Cryptographic primitives
│   │   ├── mod.rs           # Hybrid encryption with forward secrecy
│   │   ├── keys.rs          # X25519 + Ed25519 key generation, PEM format
│   │   ├── asymmetric.rs    # X25519 + ChaCha20-Poly1305 encryption
│   │   ├── symmetric.rs     # Passphrase-based encryption (HKDF + ChaCha20)
│   │   ├── signing.rs       # Ed25519 digital signatures
│   │   ├── compression.rs   # DEFLATE message compression
│   │   ├── multi_recipient.rs # Multi-recipient encryption scheme
│   │   └── ephemeral_store.rs # Contact key management for ratchet
│   │
│   ├── text/                # Text and carrier processing
│   │   ├── mod.rs           # Module exports
│   │   ├── carrier.rs       # Universal carrier abstraction (text/binary)
│   │   ├── fragment.rs      # Adaptive message fragmentation
│   │   ├── tokenize.rs      # Carrier search utilities
│   │   ├── permute.rs       # Carrier permutation, distributed selection
│   │   ├── padding.rs       # Block padding (256-char blocks)
│   │   └── suffix_array.rs  # O(m·log n) substring search
│   │
│   ├── qr/                  # QR code support
│   │   ├── mod.rs           # Base45 encoding for QR codes
│   │   ├── generator.rs     # QR code generation (PNG/SVG/ASCII)
│   │   └── reader.rs        # QR code reading and decoding
│   │
│   ├── encoder.rs           # Encoding pipeline: fragment → find → pad → encrypt
│   └── decoder.rs           # Decoding pipeline: decrypt → extract (never fails)
│
├── tests/
│   └── integration_tests.rs # End-to-end tests
│
├── .github/
│   └── workflows/
│       └── release.yml      # CI/CD: build + publish on tag
│
├── Cargo.toml
├── LICENSE
├── README.md                # User manual
├── ARCHITECTURE.md          # This file
└── CHANGELOG.md             # Version history
```

## Design Patterns

### Strategy Pattern (Commands)

Each CLI command implements the `CommandExecutor` trait:

```rust
pub trait CommandExecutor {
    fn execute(&self) -> Result<()>;
}
```

This allows:
- Clean separation of concerns
- Easy addition of new commands
- Independent testing of each command
- Minimal `main.rs` (~90 lines)

### Never-Fail Decoder

The decoder **never returns an error**. Invalid inputs produce deterministic garbage:

```rust
// Always returns a result, never Err
fn decode(&self) -> DecodedMessage {
    // Wrong passphrase? Different fragmentation → garbage from carrier
    // Wrong carrier? Wrong positions → garbage
    // Invalid base64? Hash-derived garbage
}
```

This provides:
- Plausible deniability
- Anti-brute-force (no success/fail signal)
- Deterministic garbage (same wrong inputs = same output)

## Cryptographic Architecture

### Encryption Flow

```
Message → Compress → Sign (optional) → Symmetric Encrypt → Asymmetric Encrypt → Base64
```

1. **Compression**: DEFLATE (only if it reduces size)
2. **Signing**: Ed25519 signature of message hash (optional)
3. **Symmetric**: ChaCha20-Poly1305 with HKDF-derived key from passphrase
4. **Asymmetric**: X25519 ECDH + ChaCha20-Poly1305 with ephemeral keys

### Forward Secrecy

Each message uses an ephemeral X25519 keypair:

```rust
// Encrypt
let ephemeral = EphemeralSecret::random();
let shared = ephemeral.diffie_hellman(&recipient_public);
// Ciphertext includes ephemeral public key

// Decrypt
let shared = recipient_secret.diffie_hellman(&ephemeral_public);
```

### Forward Secrecy Ratchet

The ratchet provides key rotation per message:

```rust
// EncoderConfig with ratchet enabled
let config = EncoderConfig {
    ratchet: true,
    ..Default::default()
};

// Encode generates next keypair
let result = encode_with_config(..., &config);
// result.next_keypair contains the next public/private key pair

// EncodedData includes next_public_key
struct EncodedData {
    next_public_key: Option<Vec<u8>>,  // 32 bytes X25519 public key
    // ...
}
```

Ratchet workflow:
1. Alice encodes with `--ratchet`, generates next keypair
2. Message includes Alice's next public key (encrypted)
3. Bob decodes, receives `next_public_key` for reply
4. Bob uses that key for his reply
5. Keys rotate with each message exchange

Key types distinguished by PEM headers:
- `ANYHIDE PUBLIC KEY` / `ANYHIDE PRIVATE KEY` - Static keys
- `ANYHIDE EPHEMERAL PUBLIC KEY` / `ANYHIDE EPHEMERAL PRIVATE KEY` - Rotating keys

### Ephemeral Key Storage Formats

Three storage formats for managing contacts and their ephemeral keys:

**1. Individual PEM files** (`.pub`, `.key`)
- Standard PEM format with EPHEMERAL headers
- One file per key, like long-term keys
- Best for: simple CLI usage, single contact

**2. Separate consolidated JSON** (`.eph.key`, `.eph.pub`)
- JSON with contact → key mapping
- Separate files for private and public keys
- Best for: multiple contacts, security separation

```json
// .eph.key format
{
  "version": 1,
  "contacts": {
    "bob": { "key": "base64..." },
    "alice": { "key": "base64..." }
  }
}
```

**3. Unified JSON** (`.eph`)
- Single file with both keys per contact
- `my_private`: your key for this contact
- `their_public`: contact's current public key
- Best for: chat applications, automated ratchet

```json
// .eph format
{
  "version": 1,
  "contacts": {
    "bob": {
      "my_private": "base64...",
      "their_public": "base64..."
    }
  }
}
```

### Key Derivation

All key derivation uses HKDF-SHA256 with domain-specific salts:

```rust
const HKDF_INFO: &[u8] = b"KAMO-V3-SYMMETRIC";  // Legacy salt (DO NOT CHANGE)
const HKDF_SALT: &[u8] = b"KAMO-V3-SALT-2024";  // Legacy salt (DO NOT CHANGE)
```

**Important**: Cryptographic salts use the legacy "KAMO" prefix for backwards compatibility. Do not change these values.

### Key Format (PEM)

```
# Static keys (long-term)
-----BEGIN ANYHIDE PUBLIC KEY-----
[base64 of 32 bytes X25519 public key]
-----END ANYHIDE PUBLIC KEY-----

-----BEGIN ANYHIDE PRIVATE KEY-----
[base64 of 32 bytes X25519 secret key]
-----END ANYHIDE PRIVATE KEY-----

# Signing keys
-----BEGIN ANYHIDE SIGNING PUBLIC KEY-----
[base64 of 32 bytes Ed25519 public key]
-----END ANYHIDE SIGNING PUBLIC KEY-----

-----BEGIN ANYHIDE SIGNING KEY-----
[base64 of 32 bytes Ed25519 secret key]
-----END ANYHIDE SIGNING KEY-----

# Ephemeral keys (for ratchet)
-----BEGIN ANYHIDE EPHEMERAL PUBLIC KEY-----
[base64 of 32 bytes X25519 public key]
-----END ANYHIDE EPHEMERAL PUBLIC KEY-----

-----BEGIN ANYHIDE EPHEMERAL PRIVATE KEY-----
[base64 of 32 bytes X25519 secret key]
-----END ANYHIDE EPHEMERAL PRIVATE KEY-----
```

## Encoding Pipeline

### Fragment Generation

Messages are fragmented based on passphrase-derived sizes:

```rust
// HKDF derives fragment sizes from passphrase
let sizes = derive_fragment_sizes(passphrase, message_len);
// e.g., "hello world" → ["hel", "lo", " ", "wor", "ld"]
```

### Position Selection

Fragments are found as substrings (text) or byte sequences (binary):

```rust
// Text carrier: case-insensitive substring search
"ama" found in "Amanda" at position 2

// Binary carrier: exact byte sequence match
[0x48, 0x65] found at position 1024
```

Multiple occurrences use distributed selection (passphrase-based randomization).

### Block Padding

Messages are padded to 256-character blocks with random carrier substrings:

```rust
const BLOCK_SIZE: usize = 256;
const MIN_SIZE: usize = 64;

// "hello" (5 chars) → padded to 256 chars with carrier fragments
```

## Building & Testing

```bash
# Development
cargo build
cargo test
cargo clippy

# Release
cargo build --release

# Run specific test
cargo test test_encode_decode_roundtrip

# Generate docs
cargo doc --open
```

## Code Quality Standards

All code follows SOLID principles:

- **Single Responsibility**: Each module handles one concern
- **Open/Closed**: Extensible through traits (`CommandExecutor`, `Carrier`)
- **Liskov Substitution**: Text and Binary carriers are interchangeable
- **Interface Segregation**: Small, focused traits
- **Dependency Inversion**: Core logic uses abstractions, not concretions

## Adding a New Command

1. Create `src/commands/newcmd.rs`:

```rust
use clap::Args;
use super::CommandExecutor;

#[derive(Args, Debug)]
pub struct NewCommand {
    #[arg(short, long)]
    pub option: String,
}

impl CommandExecutor for NewCommand {
    fn execute(&self) -> Result<()> {
        // Implementation
        Ok(())
    }
}
```

2. Add to `src/commands/mod.rs`:

```rust
mod newcmd;
pub use newcmd::NewCommand;
```

3. Add to `src/main.rs` enum and match.

## CI/CD Pipeline

On tag push (`v*`):
1. Build for 5 platforms (Linux x86_64/aarch64, macOS x86_64/aarch64, Windows)
2. Create GitHub Release with binaries
3. Publish to crates.io

## Version History

See [CHANGELOG.md](CHANGELOG.md) for detailed version history.