diff --git a/GEMINI.md b/GEMINI.md
index 61bbd27..e900f30 100644
--- a/GEMINI.md
+++ b/GEMINI.md
@@ -2,7 +2,7 @@
## Project Overview
-**SeedPGP v1.4.2**: Client-side BIP39 mnemonic encryption webapp
+**SeedPGP v1.4.3**: Client-side BIP39 mnemonic encryption webapp
**Stack**: Bun + Vite + React + TypeScript + OpenPGP.js + Tailwind CSS
**Deploy**: GitHub Pages (public repo: `seedpgp-web-app`, private source: `seedpgp-web`)
**Live URL**:
@@ -130,9 +130,23 @@ bun run preview # Preview production build
### Deployment Process
-1. **Private repo** (`seedpgp-web`): Source code, development
-2. **Public repo** (`seedpgp-web-app`): Built files for GitHub Pages
-3. **Deploy script** (`scripts/deploy.sh`): Builds + copies to dist/ + pushes to public repo
+**Production:** Cloudflare Pages (auto-deploys from `main` branch)
+**Live URL:**
+
+### Cloudflare Pages Setup
+
+1. **Repository:** `seedpgp-web` (private repo)
+2. **Build command:** `bun run build`
+3. **Output directory:** `dist/`
+4. **Security headers:** Automatically enforced via `public/_headers`
+
+### Benefits Over GitHub Pages
+
+- ✅ Real CSP header enforcement (blocks network requests at browser level)
+- ✅ Custom security headers (X-Frame-Options, X-Content-Type-Options)
+- ✅ Auto-deploy on push to main
+- ✅ Build preview for PRs
+- ✅ Better performance (global CDN)
### Git Workflow
@@ -141,10 +155,19 @@ bun run preview # Preview production build
git add src/
git commit -m "feat(v1.x): description"
-# Tag version
+# Tag version (triggers auto-deploy to Cloudflare)
git tag v1.x.x
git push origin main --tags
+# **IMPORTANT: Update README.md before tagging**
+# Update the following sections in README.md:
+# - Current version number in header
+# - Recent Changes section with new features
+# - Any new usage instructions or screenshots
+# Then commit the README update:
+git add README.md
+git commit -m "docs: update README for v1.x.x"
+
# Deploy to GitHub Pages
./scripts/deploy.sh v1.x.x
```
@@ -291,7 +314,7 @@ await window.runSessionCryptoTest()
---
-## Current Version: v1.4.2
+## Current Version: v1.4.3
*Please update the "Recent Changes", "Known Limitations", and "Next Priorities" sections to reflect the current state of the project.*
@@ -353,7 +376,6 @@ Check:
Output: ✅ or ❌ for each item + suggest fixes for failures.
```
-
---
**Last Updated**: 2026-01-29
diff --git a/README.md b/README.md
index f7d8053..f43ef9a 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
-# SeedPGP v1.1.0
+# SeedPGP v1.4.3
**Secure BIP39 mnemonic backup using PGP encryption and QR codes**
-A TypeScript/Bun tool for encrypting cryptocurrency seed phrases with OpenPGP and encoding them as QR-friendly Base45 frames with CRC16 integrity checking.
+A client-side web app for encrypting cryptocurrency seed phrases with OpenPGP and encoding them as QR-friendly Base45 frames with CRC16 integrity checking.
+
+**Live App:**
## Features
@@ -11,7 +13,11 @@ A TypeScript/Bun tool for encrypting cryptocurrency seed phrases with OpenPGP an
- ✅ **Integrity Checking**: CRC16-CCITT-FALSE checksums prevent corruption
- 🔑 **BIP39 Support**: Full support for 12/18/24-word mnemonics with passphrase indicator
- 🧪 **Battle-Tested**: Validated against official Trezor BIP39 test vectors
-- ⚡ **Fast**: Built with Bun runtime for optimal performance
+- ⚡ **Fast**: Built with Bun runtime and Vite for optimal performance
+- 🔒 **Session-Key Encryption**: Ephemeral AES-GCM-256 encryption for in-memory protection
+- 🛡️ **CSP Enforcement**: Real Content Security Policy headers block all network requests
+- 📸 **QR Scanner**: Camera and file upload support for scanning encrypted QR codes
+- 👁️ **Security Monitoring**: Real-time storage monitoring and clipboard tracking
## Installation
@@ -32,7 +38,30 @@ bun run dev
## Usage
-### Encrypt a Mnemonic
+### Web Interface
+
+Visit or run locally:
+
+```bash
+bun run dev
+# Open http://localhost:5173
+```
+
+**Backup Flow:**
+
+1. Enter your BIP39 mnemonic (12/18/24 words)
+2. Import PGP public key or set encryption password
+3. Click "Backup" to encrypt and generate QR code
+4. Save/print QR code for offline storage
+
+**Restore Flow:**
+
+1. Scan QR code or paste encrypted text
+2. Import PGP private key or enter password
+3. Click "Restore" to decrypt mnemonic
+4. Mnemonic auto-clears after 10 seconds
+
+### API Usage
```typescript
import { encryptToSeedPgp, buildPlaintext } from "./lib/seedpgp";
@@ -64,106 +93,42 @@ console.log(decrypted.w); // Recovered mnemonic
console.log(decrypted.pp); // BIP39 passphrase indicator (0 or 1)
```
-## Deployment to GitHub Pages (FREE)
+## Deployment
-This project uses a two-repository setup to keep source code private while hosting the app for free.
+**Production:** Cloudflare Pages (auto-deploys from `main` branch)
+**Live URL:**
-### One-Time Setup
+### Cloudflare Pages Setup
-#### 1. Create Public Deployment Repo
+This project is deployed on Cloudflare Pages for enhanced security features:
-Go to https://github.com/new and create:
-- **Name**: `seedpgp-web-app` (or any name you prefer)
-- **Visibility**: **Public**
-- **Don't** initialize with README, .gitignore, or license
+1. **Repository:** `seedpgp-web` (private repo)
+2. **Build command:** `bun run build`
+3. **Output directory:** `dist/`
+4. **Security headers:** Automatically enforced via `public/_headers`
-#### 2. Configure Vite Base Path
+### Benefits Over GitHub Pages
-Edit `vite.config.ts`:
+- ✅ Real CSP header enforcement (blocks network requests at browser level)
+- ✅ Custom security headers (X-Frame-Options, X-Content-Type-Options)
+- ✅ Auto-deploy on push to main
+- ✅ Build preview for PRs
+- ✅ Better performance (global CDN)
+- ✅ Cost: $0/month
-```typescript
-export default defineConfig({
- plugins: [react()],
- base: '/seedpgp-web-app/', // Match your public repo name
-})
-```
-
-#### 3. Build and Deploy
+### Deployment Workflow
```bash
-# Build the production bundle
-bun run build
+# Commit feature
+git add src/
+git commit -m "feat(v1.x): description"
-# Initialize git in dist folder
-cd dist
-git init
-git add .
-git commit -m "Deploy seedpgp v1.1.0"
-
-# Push to your public repo
-git remote add origin https://github.com/kccleoc/seedpgp-web-app.git
-git branch -M main
-git push -u origin main
-
-# Return to project root
-cd ..
+# Tag version (triggers auto-deploy to Cloudflare)
+git tag v1.x.x
+git push origin main --tags
```
-#### 4. Enable GitHub Pages
-
-1. Go to `https://github.com/kccleoc/seedpgp-web-app/settings/pages`
-2. **Source**: Deploy from a branch
-3. **Branch**: Select `main` → `/` (root)
-4. Click **Save**
-
-Wait 1-2 minutes, then visit: **https://kccleoc.github.io/seedpgp-web-app/**
-
----
-
-### Deploying Updates (v1.2.0, v1.3.0, etc.)
-
-Create `scripts/deploy.sh` in your project root:
-
-```bash
-#!/bin/bash
-set -e
-
-VERSION=$1
-
-if [ -z "$VERSION" ]; then
- echo "Usage: ./scripts/deploy.sh v1.2.0"
- exit 1
-fi
-
-echo "🔨 Building $VERSION..."
-bun run build
-
-echo "📦 Deploying to GitHub Pages..."
-cd dist
-git add .
-git commit -m "Deploy $VERSION" || echo "No changes to commit"
-git push
-
-cd ..
-echo "✅ Deployed to https://kccleoc.github.io/seedpgp-web-app/"
-echo "🏷️ Don't forget to tag: git tag $VERSION && git push --tags"
-```
-
-Make executable and use:
-
-```bash
-chmod +x scripts/deploy.sh
-./scripts/deploy.sh v1.2.0
-```
-
----
-
-### Repository Structure
-
-- **seedpgp-web** (Private) - Your source code, active development
-- **seedpgp-web-app** (Public) - Built files only, served via GitHub Pages
-
-**Cost: $0/month** ✅
+**No manual deployment needed!** Cloudflare Pages auto-deploys when you push to `main`.
## Frame Format
@@ -183,6 +148,7 @@ BASE45 - Base45-encoded PGP message
Creates a SeedPGP plaintext object.
**Parameters:**
+
- `mnemonic` (string): BIP39 mnemonic phrase (12/18/24 words)
- `bip39PassphraseUsed` (boolean): Whether a BIP39 passphrase was used
- `recipientFingerprints` (string[]): Optional array of recipient key fingerprints
@@ -194,6 +160,7 @@ Creates a SeedPGP plaintext object.
Encrypts a plaintext object to SeedPGP format.
**Parameters:**
+
```typescript
{
plaintext: SeedPgpPlaintext;
@@ -203,6 +170,7 @@ Encrypts a plaintext object to SeedPGP format.
```
**Returns:**
+
```typescript
{
framed: string; // SEEDPGP1 frame
@@ -216,6 +184,7 @@ Encrypts a plaintext object to SeedPGP format.
Decrypts a SeedPGP frame.
**Parameters:**
+
```typescript
{
frameText: string; // SEEDPGP1 frame
@@ -256,6 +225,8 @@ bun test --watch
- **cv25519** provides ~128-bit security level
- **CRC16** detects QR scan errors (not cryptographic)
- Key fingerprint validation prevents wrong-key usage
+- **Session-key encryption**: Ephemeral AES-GCM-256 for in-memory protection
+- **CSP headers**: Browser-enforced network blocking via Cloudflare Pages
### ⚠️ Important Notes
@@ -267,50 +238,129 @@ bun test --watch
### 🔒 Production Deployment Warning
-The GitHub Pages deployment at **https://kccleoc.github.io/seedpgp-web-app/** is for:
-- ✅ Testing and demonstration
-- ✅ Convenient access for personal use
+The Cloudflare Pages deployment at **** is for:
+
+- ✅ Personal use with enhanced security
+- ✅ CSP enforcement blocks all network requests
+- ✅ Convenient access from any device
- ⚠️ Always verify the URL before use
For maximum security with real funds:
+
- Run locally: `bun run dev`
- Or self-host on your own domain with HTTPS
+- Use an airgapped device for critical operations
+
+### Threat Model (Honest)
+
+**What we protect against:**
+
+- Accidental persistence to localStorage/sessionStorage
+- Plaintext secrets lingering in React state after use
+- Clipboard history exposure (with warnings)
+
+**What we DON'T protect against:**
+
+- Active XSS or malicious browser extensions
+- Memory dumps or browser crash reports
+- JavaScript garbage collection timing (non-deterministic)
## Project Structure
```
seedpgp-web/
├── src/
+│ ├── components/
+│ │ ├── PgpKeyInput.tsx # PGP key import UI
+│ │ ├── QrDisplay.tsx # QR code generation
+│ │ ├── QrScanner.tsx # Camera + file scanner
+│ │ ├── ReadOnly.tsx # Read-only mode toggle
+│ │ ├── StorageIndicator.tsx # Storage monitoring
+│ │ ├── SecurityWarnings.tsx # Context alerts
+│ │ └── ClipboardTracker.tsx # Clipboard monitoring
│ ├── lib/
-│ │ ├── seedpgp.ts # Core encryption/decryption
-│ │ ├── seedpgp.test.ts # Test vectors
-│ │ ├── base45.ts # Base45 codec
-│ │ ├── crc16.ts # CRC16-CCITT-FALSE
-│ │ └── types.ts # TypeScript definitions
-│ └── App.tsx # React UI
-├── scripts/
-│ └── deploy.sh # Deployment automation
+│ │ ├── seedpgp.ts # Core encryption/decryption
+│ │ ├── seedpgp.test.ts # Test vectors
+│ │ ├── sessionCrypto.ts # Ephemeral session keys
+│ │ ├── base45.ts # Base45 codec
+│ │ ├── crc16.ts # CRC16-CCITT-FALSE
+│ │ ├── qr.ts # QR utilities
+│ │ └── types.ts # TypeScript definitions
+│ ├── App.tsx # Main application
+│ └── main.tsx # React entry point
+├── public/
+│ └── _headers # Cloudflare CSP headers
├── package.json
-├── DEVELOPMENT.md # Development guide
-└── README.md # This file
+├── vite.config.ts # Vite configuration
+├── GEMINI.md # AI agent project brief
+└── README.md # This file
```
## Tech Stack
- **Runtime**: [Bun](https://bun.sh) v1.3.6+
-- **Language**: TypeScript
+- **Language**: TypeScript (strict mode)
- **Crypto**: [OpenPGP.js](https://openpgpjs.org) v6.3.0
- **Framework**: React + Vite
+- **UI**: Tailwind CSS
+- **Icons**: lucide-react
+- **QR**: html5-qrcode, qrcode
- **Testing**: Bun test runner
+- **Deployment**: Cloudflare Pages
+
+## Version History
+
+### v1.4.3 (2026-01-30)
+
+- ✅ Fixed textarea contrast for readability
+- ✅ Fixed overlapping floating boxes
+- ✅ Polished UI with modern crypto wallet design
+- ✅ Updated background color to be lighter
+
+### v1.4.2 (2026-01-30)
+
+- ✅ Migrated to Cloudflare Pages for real CSP enforcement
+- ✅ Added "Encrypted in memory" badge when mnemonic locked
+- ✅ Improved security header configuration
+- ✅ Updated deployment documentation
+
+### v1.4.0 (2026-01-29)
+
+- ✅ Extended session-key encryption to Restore flow
+- ✅ Added 10-second auto-clear timer for restored mnemonic
+- ✅ Added manual Hide button for immediate clearing
+- ✅ Removed debug console logs from production
+
+### v1.3.0 (2026-01-28)
+
+- ✅ Implemented ephemeral session-key encryption (AES-GCM-256)
+- ✅ Auto-clear mnemonic after QR generation (Backup flow)
+- ✅ Encrypted cache for sensitive state
+- ✅ Manual Lock/Clear functionality
+
+### v1.2.0 (2026-01-27)
+
+- ✅ Added storage monitoring (StorageIndicator)
+- ✅ Added security warnings (context-aware)
+- ✅ Added clipboard tracking
+- ✅ Implemented read-only mode
+
+### v1.1.0 (2026-01-26)
+
+- ✅ Initial public release
+- ✅ QR code generation and scanning
+- ✅ Full BIP39 mnemonic support
+- ✅ Trezor test vector validation
+- ✅ Production-ready implementation
## Roadmap
-- [ ] QR code generation UI
-- [ ] QR code scanner with camera support
+- [ ] UI polish (modern crypto wallet design)
- [ ] Multi-frame support for larger payloads
- [ ] Hardware wallet integration
- [ ] Mobile scanning app
- [ ] Shamir Secret Sharing support
+- [ ] Reproducible builds with git hash verification
## License
@@ -320,47 +370,6 @@ MIT License - see LICENSE file for details
**kccleoc** - [GitHub](https://github.com/kccleoc)
-## Version History
-
-### v1.1.0 (2026-01-28)
-- Initial public release
-- Full BIP39 mnemonic support
-- Trezor test vector validation
-- Production-ready implementation
-- GitHub Pages deployment guide
-
---
⚠️ **Disclaimer**: This software is provided as-is. Always test thoroughly before trusting with real funds. The author is not responsible for lost funds due to software bugs or user error.
-
-Now create the deployment script:
-
-```bash
-mkdir -p scripts
-cat > scripts/deploy.sh << 'EOF'
-#!/bin/bash
-set -e
-
-VERSION=$1
-
-if [ -z "$VERSION" ]; then
- echo "Usage: ./scripts/deploy.sh v1.2.0"
- exit 1
-fi
-
-echo "🔨 Building $VERSION..."
-bun run build
-
-echo "📦 Deploying to GitHub Pages..."
-cd dist
-git add .
-git commit -m "Deploy $VERSION" || echo "No changes to commit"
-git push
-
-cd ..
-echo "✅ Deployed to https://kccleoc.github.io/seedpgp-web-app/"
-echo "🏷️ Don't forget to tag: git tag $VERSION && git push --tags"
-EOF
-
-chmod +x scripts/deploy.sh
-```
diff --git a/package.json b/package.json
index 82f8859..14bcf45 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "seedpgp-web",
"private": true,
- "version": "1.4.2",
+ "version": "1.4.3",
"type": "module",
"scripts": {
"dev": "vite",