mirror of
https://github.com/kccleoc/seedpgp-web.git
synced 2026-03-06 17:37:51 +08:00
- Update version to v1.4.4 - Add explicit threat model documentation - Document known limitations prominently - Include air-gapped usage recommendations - Polish all documentation for clarity and examples - Update README, DEVELOPMENT.md, GEMINI.md, RECOVERY_PLAYBOOK.md
7.2 KiB
7.2 KiB
Here's your DEVELOPMENT.md:
# Development Guide - SeedPGP v1.4.4
## Architecture Quick Reference
### Core Types
```typescript
// src/lib/types.ts
interface SeedPgpPlaintext {
v: number; // Version (always 1)
t: string; // Type ("bip39")
w: string; // Mnemonic words (normalized)
l: string; // Language ("en")
pp: number; // BIP39 passphrase used? (0 or 1)
fpr?: string[]; // Optional recipient fingerprints
}
interface ParsedSeedPgpFrame {
kind: "single"; // Frame type
crc16: string; // 4-digit hex checksum
b45: string; // Base45 payload
}
Frame Format
SEEDPGP1:0:ABCD:BASE45DATA
SEEDPGP1 - Protocol identifier + version
0 - Frame number (single frame)
ABCD - CRC16-CCITT-FALSE checksum (4 hex digits)
BASE45 - Base45-encoded PGP binary message
Key Functions
Encryption Flow
buildPlaintext(mnemonic, bip39PassphraseUsed, recipientFingerprints?)
→ SeedPgpPlaintext
encryptToSeedPgp({ plaintext, publicKeyArmored?, messagePassword? })
→ { framed: string, pgpBytes: Uint8Array, recipientFingerprint?: string }
Decryption Flow
decryptSeedPgp({ frameText, privateKeyArmored?, privateKeyPassphrase?, messagePassword? })
→ SeedPgpPlaintext
frameDecodeToPgpBytes(frameText)
→ Uint8Array (with CRC16 validation)
Encoding/Decoding
frameEncode(pgpBinary: Uint8Array) → "SEEDPGP1:0:CRC16:BASE45"
frameParse(text: string) → ParsedSeedPgpFrame
frameDecodeToPgpBytes(frameText: string) → Uint8Array
Dependencies
{
"openpgp": "^6.3.0", // PGP encryption (curve25519Legacy)
"bun-types": "latest", // Bun runtime types
"react": "^18.x", // UI framework
"vite": "^5.x" // Build tool
}
OpenPGP.js v6 Quirks
⚠️ Important compatibility notes:
-
Empty password array bug: Never pass
passwords: []todecrypt(). Only include if non-empty:if (msgPw) { decryptOptions.passwords = [msgPw]; } -
Curve naming: Use
curve25519Legacy(notcurve25519) ingenerateKey() -
Key validation: Always call
getEncryptionKey()to verify public key has usable subkeys
Project Structure
seedpgp-web/
├── src/
│ ├── lib/
│ │ ├── seedpgp.ts # Core encrypt/decrypt logic
│ │ ├── seedpgp.test.ts # Test vectors (15 tests)
│ │ ├── base45.ts # Base45 encoder/decoder
│ │ ├── crc16.ts # CRC16-CCITT-FALSE
│ │ └── types.ts # TypeScript interfaces
│ ├── App.tsx # React UI entry
│ └── main.tsx # Vite bootstrap
├── package.json
├── tsconfig.json
├── vite.config.ts
├── README.md
└── DEVELOPMENT.md # This file
Development Workflow
Running Tests
# All tests
bun test
# Watch mode
bun test --watch
# Verbose output
bun test --verbose
Development Server
bun run dev # Start Vite dev server
bun run build # Production build
bun run preview # Preview production build
Adding Features
- Write tests first in
seedpgp.test.ts - Implement in
src/lib/seedpgp.ts - Update types in
types.tsif needed - Run full test suite:
bun test - Commit with conventional commits:
feat: add QR generation
Feature Agenda
🚧 v1.2.0 - QR Code Round-Trip
Goal: Read back QR code and decrypt with user-provided credentials
Tasks:
-
Add QR code generation from
encrypted.framed- Library:
qrcodeorqr-code-styling - Input: SEEDPGP1 frame string
- Output: QR code image/canvas/SVG
- Library:
-
Add QR code scanner UI
- Library:
html5-qrcodeorjsqr - Camera/file upload input
- Parse scanned text →
frameText
- Library:
-
Build decrypt UI form
- Input fields:
- Scanned QR text (auto-filled)
- Private key (file upload or paste)
- Key passphrase (password input)
- OR message password (alternative)
- Call
decryptSeedPgp() - Display recovered mnemonic + metadata
- Input fields:
-
Add visual feedback
- CRC16 validation status
- Key fingerprint match indicator
- Decryption success/error states
API Usage:
// Generate QR
import QRCode from 'qrcode';
const { framed } = await encryptToSeedPgp({ ... });
const qrDataUrl = await QRCode.toDataURL(framed);
// Scan and decrypt
const scannedText = "SEEDPGP1:0:ABCD:..."; // from scanner
const decrypted = await decryptSeedPgp({
frameText: scannedText,
privateKeyArmored: userKey,
privateKeyPassphrase: userPassword,
});
console.log(decrypted.w); // Recovered mnemonic
Security Notes:
- Never log decrypted mnemonics in production
- Clear sensitive data from memory after use
- Validate CRC16 before attempting decrypt
- Show key fingerprint for user verification
🔮 Future Ideas (v1.3+)
- Multi-frame support (for larger payloads)
- Password-only (SKESK) encryption flow
- Shamir Secret Sharing integration
- Hardware wallet key generation
- Mobile companion app (React Native)
- Printable paper backup templates
- Encrypted cloud backup with PBKDF2
- BIP85 child mnemonic derivation
Debugging Tips
Enable verbose PGP logging
Uncomment in seedpgp.ts:
console.log("Raw PGP hex:", Array.from(pgpBytes).map(...));
console.log("SeedPGP: message packets:", ...);
console.log("SeedPGP: encryption key IDs:", ...);
Test with known vectors
Use Trezor vectors from test file:
bun test "Trezor" # Run only Trezor tests
Validate frame manually
import { frameParse } from "./lib/seedpgp";
const parsed = frameParse("SEEDPGP1:0:ABCD:...");
console.log(parsed); // Check structure
Code Style
- Functions: Async by default, explicit return types
- Errors: Throw descriptive Error objects with context
- Naming:
camelCasefor functions,PascalCasefor types - Comments: Only for non-obvious crypto/encoding logic
- Testing: One test per edge case, descriptive names
Git Workflow
# Feature branch
git checkout -b feat/qr-generation
# Conventional commits
git commit -m "feat(qr): add QR code generation"
git commit -m "test(qr): add QR round-trip test"
# Tag releases
git tag -a v1.2.0 -m "Release v1.2.0 - QR round-trip"
git push origin main --tags
Questions for Next Session
When continuing development, provide:
- Feature context: "Adding QR code generation for v1.2.0"
- Current code: Paste relevant files you're modifying
- Specific question: "How should I structure the QR scanner component?"
Example starter prompt:
I'm working on seedpgp-web v1.1.0 (BIP39 PGP encryption tool).
[Paste this DEVELOPMENT.md section]
[Paste relevant source files]
I want to add QR code generation. Here's my current seedpgp.ts...
Last Updated: 2026-01-28
Maintainer: @kccleoc
Now commit it:
```bash
git add DEVELOPMENT.md
git commit -m "docs: add development guide with v1.2.0 QR agenda"
git push origin main
Ready for your next feature sprint! 🚀📋