<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->

# Privacy Tools Reference

## Signal: Operational Security Configuration

Signal uses Double Ratchet (per-message key rotation) + X3DH (async key
agreement). Forward secrecy: compromise of current key doesn't expose past
messages. Break-in recovery: new messages regain secrecy after key ratchet.

**Sealed Sender:** Encrypts sender identity along with message body. Server sees
only recipient. Enable for all contacts by default; extend to unknown senders
(Settings > Privacy > Advanced > Sealed Sender > Allow from anyone) with
awareness that spam risk increases. Sender certificate contains unidentified
access key — `SEALED_SENDER.UNRESTRICTED` state allows zero-access-key senders.

**Safety Numbers:** 60-digit numeric code (or QR) derived from both parties'
public keys and ACIs (Account Identifiers, UUID-based). Generated via
`Fingerprint.new(5200 iterations, version=2, ourAci, ourKey, theirAci, theirKey)`.
Verify out-of-band (in person or video call) to confirm no MITM. Verification
state stored locally — changes trigger "safety number changed" alert, which
requires re-verification before sending sensitive content.

**Disappearing Messages:** Set a global default timer (Settings > Privacy > Default
Timer) — applies to all new conversations. For existing convos, set per-thread.
Recommended minimums: high-sensitivity contacts → 1 week max; default
all-contacts → 4 weeks. Note messages disappear from both sides.

**Note to Self:** Encrypted, synced across linked devices. Use as secure scratchpad.
Linked devices can read note content.

**Registration hardening:** Create a username (Settings > Account profile > Username),
then set Phone Number visibility to Nobody. Prevents phone number harvest from
Signal's user directory by anyone who doesn't already have your number.

**Group metadata:** Signal private groups store no group memberships, titles,
avatars, or attributes on server. Server handles group operations via zero-
knowledge proofs. Contact list encrypted with Signal PIN (server doesn't have it).

**Anti-pattern:** Using Signal for "anonymous" comms with your real phone number
publicly linked — sealed sender protects in-transit metadata; it doesn't hide
that your number is registered. Use username + Nobody visibility.

### Operational Signal Setup (High-Security Contact)

1. Register Signal with phone number → immediately create username
2. Settings > Privacy > Phone Number: Who Can See = Nobody, Who Can Find = Nobody
3. Settings > Privacy > Advanced > Sealed Sender > Allow from anyone
4. Settings > Privacy > Default Timer → 1 week (or per threat model)
5. Settings > Notifications > Show > No Name or Message (lock screen hardening)
6. Contact setup: initiate conversation → verify Safety Number in person or via
   video call → mark as verified (tap safety number > Mark as Verified)
7. For linked devices: Settings > Linked Devices — audit regularly; remove stale

---

## Firefox Hardening (Betterfox)

Drop Betterfox `user.js` into `~/.mozilla/firefox/<profile>/user.js`, restart.
Settings override `about:config` on each launch.

**Critical privacy prefs (Securefox layer):**
```
browser.contentblocking.category = strict      // ETP strict + Total Cookie Protection
dom.security.https_only_mode = true            // HTTPS-only, no silent HTTP fallback
browser.cache.disk.enable = false              // No disk cache (prevents forensic recovery)
network.http.speculative-parallel-limit = 0   // No speculative connections
network.dns.disablePrefetch = true             // No DNS prefetch
network.prefetch-next = false                  // No link prefetch
privacy.globalprivacycontrol.enabled = true    // Send GPC signal to all sites
network.http.referer.XOriginTrimmingPolicy = 2 // Strip referer to origin only cross-origin
privacy.userContext.ui.enabled = true          // Enable containers (Firefox Multi-Account)
browser.urlbar.quicksuggest.enabled = false    // No Firefox Suggest (Bing-backed)
browser.search.suggest.enabled = false         // No search bar suggestions sent to engine
network.IDN_show_punycode = true               // Show punycode (IDN homograph phishing defense)
security.tls.enable_0rtt_data = false          // Disable TLS 1.3 0-RTT (replay attacks)
security.OCSP.enabled = 0                      // Disable OCSP (privacy: leaks visited sites)
browser.privatebrowsing.forceMediaMemoryCache = true // PB media stays in RAM
```

**Telemetry kill (all false/empty):**
```
datareporting.policy.dataSubmissionEnabled = false
toolkit.telemetry.unified = false
toolkit.telemetry.enabled = false
toolkit.telemetry.server = "data:"
app.shield.optoutstudies.enabled = false
app.normandy.enabled = false
```

**Safe browsing tightening:**
```
browser.safebrowsing.downloads.remote.enabled = false  // No remote lookup for downloads
```

**Containers workflow:** Install Firefox Multi-Account Containers extension.
Create: Work, Personal, Shopping, Banking containers. Never cross-contaminate
logged-in accounts across containers. Use Temporary Containers for one-off
anonymous browsing sessions.

**Anti-pattern:** Using uBlock Origin in default mode on a fingerprinted browser
then assuming you're "private" — ETP + disk cache disabled + no telemetry is
the baseline; uBlock adds filter-list blocking, not fingerprint protection.

---

## Cryptomator: Cloud Vault Operations

Client-side AES-256-GCM encryption before sync. Encrypts: file contents, file
names, directory names. Does NOT encrypt: file count, file sizes (approximate),
modification timestamps visible to cloud provider.

Vault structure:
```
vault/
├── masterkey.cryptomator   # Encrypted masterkey (scrypt KDF from passphrase)
├── d/                      # Encrypted file tree (files split into <DIR>/<2-char>/<30-char>.c9r)
└── vault.cryptomator       # Vault config (format version, cipher suite)
```

Key derivation: scrypt(N=32768, r=8, p=1) by default. Masterkey wrapped with
passphrase-derived key. Each file encrypted with unique random content key
(AES-SIV for filenames, AES-CTR + HMAC for content in older format; AES-GCM
in newer Vault Format 8+).

**CLI (cryptomator-cli, Java):**
```bash
# Unlock vault and mount FUSE filesystem
java -jar cryptomator-cli.jar --vault myVault:/path/to/vault \
  --password myVault:pass \
  --mount myVault:/mnt/decrypted

# Unlock with password from file (avoid shell history exposure)
java -jar cryptomator-cli.jar --vault v:/path/to/vault \
  --passwordfile v:/run/secrets/vault_pass \
  --mount v:/mnt/v
```

**Backup strategy:** Backup the `vault/` directory encrypted. The masterkey file
is the crown jewel — backup separately (offline, encrypted). Losing masterkey
= losing vault permanently.

**Anti-pattern:** Storing the vault password in plaintext near the vault folder.
Scrypt KDF is intentionally slow — use a strong passphrase (6+ words), not a
remembered PIN.

---

## VeraCrypt: Encrypted Volumes and Plausible Deniability

Volumes: file container, partition, full device. Encryption: AES-256 (recommended),
Twofish, Serpent, cascades. Hash for key derivation: SHA-512 (recommended),
Whirlpool, Blake2s. PRE: AES + SHA-512 is the safest and fastest combination.

**Container creation (Linux CLI, non-interactive):**
```bash
veracrypt --text --create /secure/container.vc \
  --size 2G \
  --password "strong-passphrase" \
  --encryption AES \
  --hash SHA-512 \
  --filesystem Ext4 \
  --pim 0 \
  --keyfiles "" \
  --random-source /dev/urandom
```

**Mount/dismount:**
```bash
# Mount to /mnt/vc
veracrypt --text --mount /secure/container.vc /mnt/vc --password "pass"
# Dismount
veracrypt --text --dismount /mnt/vc
# Dismount all
veracrypt --text --dismount
# Force dismount (files in use)
veracrypt --text --dismount --force
```

**Hidden volumes (plausible deniability):**
Outer volume contains decoy sensitive-looking content. Hidden volume occupies
the random-looking free space at the end of outer volume. Two passwords:
outer password → decoy content; hidden password → real content. Server cannot
distinguish hidden volume from random free space.

Creation sequence: create outer volume → fill with decoy files → create hidden
volume within outer (wizard detects max safe size) → store real data in hidden.
Mount with hidden password to access hidden content; mount with outer password
under duress.

**Critical:** When mounting outer volume for normal use (adding decoy content),
enable "Protect hidden volume" mode — otherwise outer volume writes may corrupt
hidden volume. Enable via: Mount > Mount Options > Protect hidden volume.

**Keyfile hardening:** Add keyfile(s) alongside password for two-factor volume
protection. Keyfile can be any file (photo, binary). Lose keyfile = lose volume.
```bash
veracrypt --text --mount /secure/container.vc /mnt/vc \
  --password "pass" --keyfiles "/path/to/keyfile.jpg"
```

**Anti-pattern:** Using Quick Format — skips random data fill, potentially
revealing volume boundaries. Always use full format for security-sensitive volumes.

---

## DNS-Based Privacy: Blocklists and Resolvers

DNS blocking is the most leverage-per-effort privacy control. Blocks ads,
tracking, malware, phishing at resolver level — affects all devices/apps.

**HaGeZi blocklist tiers** (recommended: Pro as daily driver):
- `light` — 133k domains — basic ads/tracking, no breakage
- `normal` — 301k domains — balanced; rare breakage
- `pro` — 396k domains — extended; occasional breakage (recommended)
- `pro++` — 484k domains — aggressive; some legitimate sites blocked
- `ultimate` — 546k domains — maximum; expect breakage

Supplement Pro with:
- `tif` (Threat Intelligence Feeds) — phishing/malware, minimal FP rate
- `native` — device-specific trackers (Smart TV, IoT)
- `fake` — scam/impersonation domains

**AdGuard Home setup (self-hosted, Pi/VPS):**
```bash
# Install
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

# Add blocklist in UI: Filters > DNS blocklists > Add blocklist
# HaGeZi Pro: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.txt
# HaGeZi TIF: https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/tif.txt
```

**Pi-hole (alternative):**
```bash
# Add to /etc/pihole/adlists.conf
https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/domains/pro.txt

pihole -g  # Gravity update (pull and compile lists)
```

**Encrypted DNS (DoH/DoT):** Use Quad9 (9.9.9.9, security-focused, GDPR-compliant
under Swiss law) or Mullvad DNS (privacy-first, no logging). Configure in
AdGuard Home under DNS Settings > Upstream DNS Servers:
`tls://dns.quad9.net` or `https://dns.mullvad.net/dns-query`

**Anti-pattern:** Adding HaGeZi Ultimate on a production network without a
whitelist process — legitimate CDNs and business services get blocked. Start
with Pro + TIF; escalate only if threat model requires it.

---

## Secure Secret Sharing: PrivateBin and Yopass

Both implement zero-knowledge paste/secret sharing: encryption in-browser, key
never sent to server.

**PrivateBin:**
- AES-256-GCM in browser. Decryption key in URL fragment (`#key`) — fragment
  never sent to server in HTTP requests.
- Server admin has plausible deniability (server stores only ciphertext).
- Security requirement: MUST use HTTPS (otherwise network attacker gets the key
  from URL). HSTS recommended on server.
- If URL is shared publicly, anyone with URL can decrypt. Use password option
  for additional protection — share URL and password on separate channels.
- Server can be legally compelled to inject malicious JS (trust model caveat).
  Self-host for high-sensitivity use.

**Yopass:**
- OpenPGP.js encryption in browser. One-time URL (secret deleted on first view).
- CLI: `printf 'secret' | yopass` → returns URL. `yopass --decrypt <url>` → outputs secret.
- Self-deploy: `docker run --name yopass -p 1337:1337 jhaals/yopass` (uses local memcached for TTL)
- Secrets self-destruct on retrieval + TTL expiry (1h/1d/1w).
- Recommended: self-host, never trust public instances for high-value secrets.

**Both tools:** Never use public instances for credentials, private keys, or
PII. Self-hosted instances on trusted infra only.

### Privacy Stack Deployment (Self-Hosted)

1. VPS/Pi: Install AdGuard Home → add HaGeZi Pro + TIF blocklists
2. Configure upstream: `tls://dns.quad9.net` (security) or Mullvad DoH (privacy)
3. Set router DHCP DNS to AdGuard Home IP → all devices route through it
4. Firefox: deploy Betterfox user.js → restart → verify ETP strict in Privacy Settings
5. Add Firefox Multi-Account Containers → assign contexts (work/personal/banking)
6. Cloud storage: set up Cryptomator vault in sync folder → use vault for sensitive docs
7. Device storage: VeraCrypt container for sensitive local files (or hidden volume for high-risk)
8. Secret sharing: self-host PrivateBin or Yopass → use for credential handoff

---
v1.1 | Validated: 2026-03-13
