# SeedPGP v1.4.7

**Secure BIP39 mnemonic backup using PGP encryption and QR codes**

A client-side web app for encrypting cryptocurrency seed phrases with OpenPGP and encoding them as QR-friendly Base45 frames. Designed for offline use on TailsOS with built-in security verification.

**Live Demo (Testing Only):** <https://seedpgp-web.pages.dev>

---

## 🚦 Quick Start — Recommended TailsOS Workflow

For **real funds** ($100+), follow this airgapped TailsOS workflow:

```bash
# 1. Boot TailsOS (airgapped - no network!)
# 2. Open Terminal and run:
git clone https://github.com/kccleoc/seedpgp-web.git
cd seedpgp-web

# 3. Build and verify (single command)
make full-build-tails

# 4. Serve locally in Tor Browser
make serve-local
# → Open http://localhost:8000 in Tor Browser
```

**That's it.** The Makefile handles everything: build, CSP injection, integrity verification, and security auditing.

---

## 💡 Security-First Usage Guide

| Your Fund Size | Recommended Setup | Build Command | Time |
|----------------|-------------------|---------------|------|
| **Testing** (<$100) | Any computer, local mode | `make build-offline` | 5 min |
| **Real Use** ($100–$10K) | Clean computer, network disabled | `make build-offline` | 15 min |
| **Serious** ($10K–$100K) | **TailsOS or Ubuntu Live (airgapped)** | `make full-build-tails` | 30 min |
| **Vault** (>$100K) | TailsOS + hardware wallet + multisig | `make full-build-tails` | 1+ hour |

**The more funds at stake, the more security precautions you take.**

**Note:** TailsOS and Ubuntu Live USB provide equivalent security for offline seed operations. See Path 1 (TailsOS) and Path 3 (Ubuntu Live) below for detailed workflows.

---

## 🔧 Makefile Commands Reference

### Core Build Commands

```bash
# Install dependencies
make install

# Build for Cloudflare Pages (production)
make build

# Build for offline local testing
make build-offline

# Build for TailsOS with embedded CSP + integrity checks
make build-tails

# Full TailsOS pipeline (recommended for real use)
make full-build-tails
```

### Testing & Verification

```bash
# Verify TailsOS build integrity (CSP, checksums, paths)
make verify-tails

# Verify offline compatibility
make verify-offline

# Run security audit
make audit

# Run test suite
make test
```

### Local Servers

```bash
# Serve with Python HTTP server
make serve-local

# Serve with Bun server
make serve-bun

# Development mode (hot reload)
make dev
```

### Utility

```bash
# Clean build artifacts
make clean

# Show all available commands
make help
```

---

## 🛡️ Path 1: TailsOS Airgapped Setup (RECOMMENDED for $10K+)

This is the **gold standard** for seed phrase management. Takes 30 minutes, provides maximum security.

### Why TailsOS?

- **Amnesic**: Runs entirely in RAM, leaves no trace on disk
- **Airgapped**: You physically disconnect from all networks
- **Isolated**: Browser can't access persistent storage
- **Audited**: Open-source OS trusted by journalists and activists

### Step 1: Prepare TailsOS USB

```bash
# On your primary computer:

# 1. Download Tails ISO
# Visit: https://tails.net/install/
# Download latest version (verify signature!)

# 2. Burn to USB stick
# Use Balena Etcher or dd command
# Minimum 8GB USB required

# 3. Label this USB "TAILS SEED OPS"
# Keep separate from daily-use USBs
```

### Step 2: Boot TailsOS (Airgapped)

```bash
# Physical security checklist:
□ Unplug Ethernet cable from computer
□ Disable WiFi in BIOS (if possible)
□ Put phone in airplane mode (away from desk)
□ Close curtains (prevent shoulder surfing)

# Boot process:
1. Insert TailsOS USB
2. Reboot computer
3. Press F12/ESC/DEL to enter boot menu
4. Select USB drive
5. Choose "Start Tails"
6. ⚠️ DO NOT configure WiFi when prompted
7. Verify network icon shows "disconnected"
```

### Step 3: Build SeedPGP on TailsOS

```bash
# Open Terminal (Applications → System Tools → Terminal)

# Install Bun (first time only)
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc

# Clone repository
git clone https://github.com/kccleoc/seedpgp-web.git
cd seedpgp-web

# Install dependencies
make install

# Build with security hardening
make full-build-tails
```

**Note:** All builds include a baseline CSP in index.html, but the `make full-build-tails` pipeline injects a stricter, WASM-compatible CSP tailored for TailsOS.

**What `make full-build-tails` does:**

1. **Cleans** all previous build artifacts
2. **Builds** with relative paths for offline use
3. **Injects** CSP meta tag directly into HTML
4. **Creates** `dist-tails/` directory with:
   - Complete app bundle
   - `README.txt` with SHA-256 checksums
   - Security documentation
5. **Verifies** CSP enforcement, relative paths, integrity
6. **Audits** for network calls, external URLs, security issues

### Step 4: Verify Build Integrity

The build process automatically verifies:

```bash
✅ CSP enforces connect-src 'none' (all network calls blocked)
✅ Relative paths detected (offline compatible)
✅ No suspicious external domains
ℹ️  fetch() references exist in bundle (from openpgp.js)
✓  These are BLOCKED by CSP connect-src 'none' at runtime
✅ TailsOS build verification complete
```

**Security Note:** `fetch()` and `XMLHttpRequest` references exist in the bundle (from OpenPGP.js library code), but they are **completely blocked** by CSP `connect-src 'none'` at the browser level. The verification confirms CSP enforcement, not the absence of dead code.

### Step 5: Serve Locally in Tor Browser

```bash
# Start local HTTP server
make serve-local

# Output:
# 🚀 Starting local server at http://localhost:8000
#    Press Ctrl+C to stop
```

**Open Tor Browser** (pre-installed in TailsOS):

1. Launch Tor Browser from desktop
2. Navigate to: `http://localhost:8000`
3. App loads — all processing happens locally
4. Verify "Network BLOCKED" indicator in app header

### Step 6: Use SeedPGP Securely

Now proceed to "Using SeedPGP" section below. All entropy generation, encryption, and QR generation happens offline in your browser's memory.

**When finished:**

```bash
# Stop server (Ctrl+C in Terminal)
# Shutdown TailsOS (Applications → Shutdown)
# ✅ All data erased from RAM
# ✅ No trace left on computer
```

---

## 🏠 Path 2: Local Offline Setup (Acceptable for <$10K)

For smaller amounts, you can run on a regular computer with network disabled.

```bash
# Clone repository
git clone https://github.com/kccleoc/seedpgp-web.git
cd seedpgp-web

# Install dependencies
make install

# Build for offline use
make full-build-offline

# Disconnect network NOW:
# - Unplug Ethernet
# - Disable WiFi
# - Airplane mode ON

# Serve locally
make serve-local

# Open browser: http://localhost:8000
```

**Security vs TailsOS:**

| Feature | Local Offline | TailsOS Airgapped |
|---------|---------------|-------------------|
| RAM-only execution | ❌ No | ✅ Yes |
| Disk trace | ⚠️ Possible | ✅ None |
| Extension isolation | ⚠️ Manual | ✅ Automatic |
| Memory dump protection | ❌ Limited | ✅ Strong |
| **Best for** | Testing, <$10K | $10K+, serious use |

---

## 🐧 Path 3: Ubuntu Live USB (Alternative to TailsOS)

**Ubuntu Live USB provides equivalent security to TailsOS** for offline seed operations. It's RAM-only, amnesic (data erased on shutdown), and may be more familiar if you're already comfortable with Ubuntu.

### When to Use Ubuntu Live USB

- ✅ You're already familiar with Ubuntu/Linux workflows
- ✅ You only need offline operations (no Tor required)
- ✅ You want faster boot time (~1 min vs Tails ~2 min)
- ✅ You might need to install additional tools during the session

### Security Properties

| Feature | Ubuntu Live USB | TailsOS |
|---------|-----------------|---------|
| RAM-only execution | ✅ Yes | ✅ Yes |
| Amnesic (data erased on poweroff) | ✅ Yes | ✅ Yes |
| Network isolation | ⚠️ Manual disable | ✅ Automatic (Tor-only) |
| Pre-installed crypto tools | ❌ Need Python | ✅ GPG, KeePassXC built-in |
| Boot time | ~1 min | ~2 min |
| Best for | Offline seed ops | Offline + Tor workflows |

**For your use case (offline seed blending): Both are equivalent.**

---

### Step 1: Prepare Ubuntu Live USB

**On your regular computer:**

```bash
# Download Ubuntu Desktop LTS ISO
wget https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso

# Verify SHA256 checksum
sha256sum ubuntu-24.04-desktop-amd64.iso
# Compare against official checksum from ubuntu.com/download

# Create bootable USB (Linux/Mac)
sudo dd if=ubuntu-24.04-desktop-amd64.iso of=/dev/sdX bs=4M status=progress
# ⚠️ Replace /dev/sdX with your USB device (check with 'lsblk')

# Windows: Use Rufus or balenaEtcher instead
```

**Prepare SeedPGP on a separate USB drive:**

```bash
# Clone and build on your trusted computer
git clone https://github.com/kccleoc/seedpgp-web.git
cd seedpgp-web
make install
make full-build-tails  # Creates dist-tails/ with embedded CSP

# Generate checksum file
cd dist-tails
sha256sum index.html > CHECKSUM.txt
cd ..

# Copy to second USB drive (label it "SEEDPGP-OFFLINE")
cp -r dist-tails/ /media/your-usb/seedpgp-offline/
```

**You now have:**
1. **USB #1:** Ubuntu Live bootable installer
2. **USB #2:** Pre-verified SeedPGP build with checksums

---

### Step 2: Boot Ubuntu Live (Network Disabled)

**Physical security checklist:**

```
□ Unplug Ethernet cable from computer
□ Remove SIM card (if using a laptop with cellular)
□ Put phone in airplane mode (away from desk)
□ Close curtains (prevent shoulder surfing)
```

**Boot process:**

1. Insert Ubuntu Live USB (#1)
2. Reboot computer and press **F12/F2/ESC** during startup
3. Select USB drive from boot menu
4. Choose **"Try Ubuntu"** (NOT "Install Ubuntu")
5. **IMMEDIATELY after desktop loads:** Click network icon → **Disable Wi-Fi**
6. Verify network status in terminal:

```bash
ip link show
# All interfaces should show 'state DOWN' except 'lo' (loopback)

# Confirm no external routes
ip route
# Should ONLY show: 127.0.0.0/8 dev lo
```

---

### Step 3: Verify Clean State

```bash
# Open Terminal (Ctrl+Alt+T)

# Check no mounted writable drives
mount | grep -v "ro,"
# Should only show read-only mounts (iso9660, squashfs)

# Check no swap space
swapon --show
# Should return nothing

# Verify RAM usage
free -h
# Should show ~2-4GB used (OS running entirely in RAM)
```

---

### Step 4: Load and Verify SeedPGP

```bash
# Insert USB #2 (SEEDPGP-OFFLINE)
# It will auto-mount to /media/ubuntu/SEEDPGP-OFFLINE or similar

# Navigate to the build folder
cd /media/ubuntu/*/seedpgp-offline/
# Or use: cd /media/ubuntu/SEEDPGP-OFFLINE/seedpgp-offline/

# Verify integrity before running
sha256sum -c CHECKSUM.txt
# Should output: index.html: OK

# If verification fails → STOP! Do not proceed.
# Re-build on your trusted computer and copy again.
```

---

### Step 5: Serve Locally with Python

**Important:** You cannot open `file://` URLs directly in modern browsers due to CORS restrictions. You must serve over HTTP on localhost.

```bash
# Start Python HTTP server (Python 3 is pre-installed)
python3 -m http.server 8000 &
# The '&' runs it in background

# You'll see:
# Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
```

**Security verification: Localhost is safe**

Even though the server listens on `0.0.0.0:8000` (all interfaces), there are **no active network interfaces** to reach it from outside:

```bash
# Verify localhost-only access
sudo ss -tlnp | grep 8000
# Shows: LISTEN 0.0.0.0:8000 (looks exposed, but...)

# Check which interfaces exist
ip addr show
# Should ONLY show 'lo' (loopback 127.0.0.1) with status UP
# No eth0, wlan0, or other interfaces should be UP

# Try accessing from "outside" (this should fail)
curl http://192.168.1.100:8000  # Use any typical LAN IP
# Should instantly fail: "Network unreachable"
```

**The key:** Even though Python binds to `0.0.0.0`, there are no physical network paths to reach it. Localhost is a kernel-internal loopback interface.

---

### Step 6: Open in Firefox

```bash
# Launch Firefox with localhost URL
firefox http://localhost:8000 &
```

**Verify the app loaded correctly:**

1. SeedPGP interface appears
2. Check browser console (F12) for CSP enforcement:
   - Should see no CSP violation errors
   - Network tab should show only localhost requests
3. Verify "Network BLOCKED" indicator in app header

---

### Step 7: Use SeedPGP

Now proceed with your seed operations (see "Using SeedPGP: The Workflow" section below):

- Generate entropy (dice rolls recommended)
- Blend multiple hardware wallet seeds (if applicable)
- Encrypt to PGP key or password
- Export QR backup
- **Write final seed to paper immediately**

**⚠️ CRITICAL:** Never save anything to disk. All data stays in RAM.

---

### Step 8: Shutdown and Verify Data Erasure

```bash
# Stop the Python server (not strictly necessary, but good practice)
killall python3

# Power off Ubuntu Live
sudo poweroff

# Physical verification:
□ Remove both USB drives
□ All RAM contents are erased (power loss = data loss)
□ No trace left on computer's hard drive
```

**What just happened:**

- ✅ All seed operations occurred in RAM only
- ✅ Python HTTP server never had external network access
- ✅ SeedPGP never wrote to persistent storage
- ✅ Shutdown wiped all RAM contents
- ✅ Computer's hard drive was never touched (read-only boot)

---

### Optional: Advanced Hardening

If you want to match TailsOS-level security:

**1. Disable swap (already disabled by default, but verify):**
```bash
sudo swapoff -a
```

**2. Clear clipboard before shutdown:**
```bash
# If you copied anything sensitive
echo "" | xclip -selection clipboard
```

**3. Wipe RAM on shutdown (paranoid mode):**
```bash
# For protection against cold-boot attacks (freezing RAM with liquid nitrogen)
sudo apt install secure-delete
sudo sdmem -v  # Takes ~2 min, overwrites RAM with random data
```

**Note:** For your threat model (protecting seeds from remote attackers, not physical access to frozen RAM), step 3 is unnecessary.

---

### Ubuntu Live vs TailsOS: Summary

**Use Ubuntu Live USB if:**
- You're already comfortable with Ubuntu
- You only need offline seed operations
- You want faster boot time
- You value familiarity over maximum security

**Use TailsOS if:**
- You want zero-config maximum security
- You might need Tor for other operations
- You're handling $100K+ and want the most audited option
- You want automatic MAC randomization and anti-forensics

**For your use case (three-hardware-wallet blend on Ubuntu Live): ✅ Perfectly safe.**

---

## 🔐 Using SeedPGP: The Workflow

### Step 1: Generate Entropy (New Seed)

SeedPGP offers multiple entropy sources you can combine:

```bash
🎲 Dice Rolls    - Physical randomness (99 rolls recommended)
🎥 Camera Noise  - Visual entropy from textured surfaces
🎵 Audio Input   - Microphone randomness from ambient sound
```

**Recommended: Dice Rolls (Highest Trust)**

1. Click **"Create"** tab → **"Dice Rolls"**
2. Roll physical dice 99 times
3. Enter each result (1-6)
4. App shows entropy progress bar
5. Click **"Generate Seed"**
6. **Your 12 or 24-word mnemonic appears**

**⚠️ CRITICAL:** Write down seed phrase on paper RIGHT NOW. Don't trust digital storage.

### Step 2: Encrypt Your Seed

**Option A: Password-Based Encryption (Simplest)**

```bash
1. Your seed phrase is visible in the textarea
2. Enter a strong password (25+ characters):
   Example: "Tr0pic!M0nkey$Orange#2024@Secret%Phrase"
3. Confirm password
4. Click "Generate QR Backup"
5. Screenshot or print the QR code
```

**Option B: PGP Key Encryption (Most Secure)**

```bash
# Prerequisites: Have a PGP keypair (generate with GPG)
gpg --full-generate-key  # Follow prompts
gpg --armor --export your-email@example.com > public.asc

# In SeedPGP:
1. Click "PGP Key Input"
2. Paste your public key
3. App shows fingerprint → verify it matches
4. Click "Use This Key"
5. Click "Generate QR Backup"
6. Save QR code securely
```

### Step 3: Test Recovery IMMEDIATELY

**⚠️ DO NOT SKIP THIS STEP**

```bash
1. Click "Restore" tab
2. Scan or upload your QR backup
3. Enter password OR provide private key
4. Verify decrypted seed matches original
5. If mismatch → ⚠️ DO NOT USE, redo backup
```

**Why test?** Better to find a corrupt backup now than during an emergency.

### Step 4: Store Backups Securely

You now have:

- ✅ **Paper seed** (12/24 words handwritten)
- ✅ **Encrypted QR code** (digital backup)

**Storage strategy:**

| Item | Location | Redundancy |
|------|----------|------------|
| Paper seed | Safe deposit box | Primary copy |
| Paper seed copy 2 | Home safe | Backup copy |
| QR code | USB drive in safe | Digital recovery |
| QR code copy 2 | Cloud storage (encrypted!) | Disaster recovery |
| Password/PGP key | Password manager | Encrypted separately |

**Geographic distribution:** Keep copies in different physical locations (home, office, bank vault).

---

## 🧪 Development & Testing

### Run Tests

```bash
# All tests
make test

# Individual test suites
bun test src/lib/bip39.test.ts
bun test src/lib/seedpgp.test.ts
bun test src/lib/krux.test.ts
```

### Development Mode

```bash
# Hot reload development server
make dev

# With network blocking enabled by default
VITE_NETWORK_BLOCK=true make dev
```

### Security Auditing

```bash
# Full security audit
make audit

# Output includes:
# - CSP configuration check
# - Network API usage analysis
# - Persistent storage detection
# - eval()/Function() detection
# - Defense-in-depth layer summary
```

---

## 🏗️ Build Artifacts Explained

### `make build-tails` Output

```
dist-tails/
├── index.html          # CSP injected, relative paths
├── assets/
│   ├── index-*.js     # Main bundle (minified)
│   ├── index-*.css    # Styles
│   └── secp256k1.wasm # Crypto library
└── README.txt         # SHA-256 checksums + usage instructions
```

### CSP Configuration (Embedded in HTML)

```html
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; 
               script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; 
               style-src 'self' 'unsafe-inline'; 
               img-src 'self' data: blob:; 
               connect-src 'none'; 
               font-src 'self'; 
               object-src 'none'; 
               base-uri 'self'; 
               form-action 'none';" 
      data-env="tails">
```

**Key directive:** `connect-src 'none'` — Browser refuses ALL network requests (fetch, XHR, WebSocket, etc.)

---

## 🛡️ Security Architecture

### Defense-in-Depth Layers

| Layer | Mechanism | Bypassable? | Purpose |
|-------|-----------|-------------|---------|
| **1. CSP** | `connect-src 'none'` in HTML | ❌ No (browser enforced) | **PRIMARY DEFENSE** |
| 2. Network Blocker | JS patches window.fetch/XHR | ✅ Yes (console bypass) | Defense-in-depth |
| 3. Airgapped OS | TailsOS, no network drivers | ❌ No (physical isolation) | Ultimate isolation |
| 4. Session Crypto | AES-256-GCM, non-exportable | ⚠️ Memory dumps | Protects cached data |
| 5. Auto-Clear | 10s clipboard wipe | ✅ Yes (user can cancel) | Reduces exposure window |

**Primary Security:** CSP + TailsOS = two independent layers that must BOTH fail for compromise.

### Threat Model

**What SeedPGP Protects Against:**

✅ Browser extensions stealing seed  
✅ Malicious websites accessing clipboard  
✅ Network exfiltration attempts  
✅ Accidental data leaks to localStorage  
✅ Session replay attacks  

**What SeedPGP CANNOT Protect Against:**

❌ Compromised TailsOS ISO (verify signatures!)  
❌ Hardware keyloggers  
❌ Evil maid attacks (physical device tampering)  
❌ Memory dumps from privileged malware  
❌ Social engineering (phishing for password)  

**Mitigation:** Use TailsOS (verified ISO) + physical security + test recovery immediately.

---

## 📖 Technical Documentation

- [MEMORY_STRATEGY.md](doc/MEMORY_STRATEGY.md) - Why JS can't zero memory, defense strategies
- [RECOVERY_PLAYBOOK.md](doc/RECOVERY_PLAYBOOK.md) - Offline recovery procedures
- [TAILS_OFFLINE_PLAYBOOK.md](doc/TAILS_OFFLINE_PLAYBOOK.md) - Complete TailsOS workflow
- [SeedPGP-Web-Forensic-Security-Report.pdf](doc/) - Independent security audit

---

## 🆘 Troubleshooting

### Build Issues

```bash
# Permission denied during build
sudo chmod +x Makefile
make clean && make install

# Bun not found
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc

# CSP not embedded
make clean build-tails
grep "Content-Security-Policy" dist-tails/index.html
```

### TailsOS Issues

```bash
# Can't access localhost:8000
# → Check firewall: sudo ufw allow 8000
# → Use 127.0.0.1:8000 instead

# Bun installation fails
# → TailsOS persistence required
# → Use temporary session, re-install each boot

# Camera/microphone not working
# → TailsOS may block by default
# → Use dice rolls instead (recommended anyway)
```

### Recovery Issues

```bash
# QR scan fails
# → Ensure good lighting, steady camera
# → Upload image file instead of scanning

# Decryption fails
# → Verify password exactly matches
# → Check PGP key fingerprint
# → QR may be damaged → test backup immediately after creation!
```

---

## ⚖️ License & Disclaimer

**MIT License** - See LICENSE file

**⚠️ CRITICAL DISCLAIMER:**

```
CRYPTOCURRENCY SECURITY IS YOUR RESPONSIBILITY.

This software is provided "AS IS", without warranty of any kind.

1. TEST with small amounts ($1-10) before trusting with real funds
2. VERIFY recovery works immediately after creating backup
3. STORE multiple copies in geographically distributed locations
4. USE TailsOS for amounts > $10K
5. CONSULT professional security advice for amounts > $100K

Your seed phrase = your funds. Lose the seed = lose the funds.
The author is NOT responsible for:
- Lost funds due to bugs, user error, or hardware failure
- Compromised devices or insecure storage
- Forgotten passwords or lost backups

If you don't understand how this works, start with $10 and test thoroughly.
```

---

## 🙏 Credits & Security

**Author:** kccleoc  
**Security Audit:** v1.4.7 (February 2026) - No exploits found  
**License:** MIT

**Report Security Issues:**

- Private disclosure via [GitHub Security Advisory](https://github.com/kccleoc/seedpgp-web/security)
- For urgent issues: Encrypt with PGP key in repository

**Dependencies Audited:**

- OpenPGP.js v5.11+
- BIP39 reference implementation
- jsQR for QR scanning
- secp256k1 WASM module

---

## 🚀 Quick Reference Card

```bash
# === PRODUCTION WORKFLOW (TailsOS) ===
make full-build-tails    # Build + verify + audit
make serve-local         # Serve on localhost:8000

# === DEVELOPMENT ===
make dev                 # Hot reload
make test                # Run tests
make audit               # Security audit

# === VERIFICATION ===
make verify-tails        # Check CSP, checksums, paths
grep "connect-src" dist-tails/index.html  # Manual CSP check

# === CLEANUP ===
make clean               # Remove all build artifacts
```

**Remember:** More funds = more security steps. Don't skip TailsOS for serious amounts.
