# SeedPGP v1.1.0 **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. ## Features - ๐Ÿ” **PGP Encryption**: Uses cv25519 (Curve25519) for modern elliptic curve cryptography - ๐Ÿ“ฑ **QR Code Ready**: Base45 encoding optimized for QR code generation - โœ… **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 ## Installation ```bash # Clone repository git clone https://github.com/kccleoc/seedpgp-web.git cd seedpgp-web # Install dependencies bun install # Run tests bun test # Start development server bun run dev ``` ## Usage ### Encrypt a Mnemonic ```typescript import { encryptToSeedPgp, buildPlaintext } from "./lib/seedpgp"; const mnemonic = "legal winner thank year wave sausage worth useful legal winner thank yellow"; const plaintext = buildPlaintext(mnemonic, false); // false = no BIP39 passphrase used const result = await encryptToSeedPgp({ plaintext, publicKeyArmored: yourPgpPublicKey, }); console.log(result.framed); // SEEDPGP1:0:ABCD:BASE45DATA... console.log(result.recipientFingerprint); // Key fingerprint for verification ``` ### Decrypt a SeedPGP Frame ```typescript import { decryptSeedPgp } from "./lib/seedpgp"; const decrypted = await decryptSeedPgp({ frameText: "SEEDPGP1:0:ABCD:BASE45DATA...", privateKeyArmored: yourPrivateKey, privateKeyPassphrase: "your-key-password", }); console.log(decrypted.w); // Recovered mnemonic console.log(decrypted.pp); // BIP39 passphrase indicator (0 or 1) ``` ## Frame Format ``` SEEDPGP1:FRAME:CRC16:BASE45DATA SEEDPGP1 - Protocol identifier and version 0 - Frame number (0 = single frame) ABCD - 4-digit hex CRC16-CCITT-FALSE checksum BASE45 - Base45-encoded PGP message ``` ## API Reference ### `buildPlaintext(mnemonic, bip39PassphraseUsed, recipientFingerprints?)` 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 **Returns:** `SeedPgpPlaintext` object ### `encryptToSeedPgp(params)` Encrypts a plaintext object to SeedPGP format. **Parameters:** ```typescript { plaintext: SeedPgpPlaintext; publicKeyArmored?: string; // PGP public key (PKESK) messagePassword?: string; // Symmetric password (SKESK) } ``` **Returns:** ```typescript { framed: string; // SEEDPGP1 frame pgpBytes: Uint8Array; // Raw PGP message recipientFingerprint?: string; // Key fingerprint } ``` ### `decryptSeedPgp(params)` Decrypts a SeedPGP frame. **Parameters:** ```typescript { frameText: string; // SEEDPGP1 frame privateKeyArmored?: string; // PGP private key privateKeyPassphrase?: string; // Key unlock password messagePassword?: string; // SKESK password } ``` **Returns:** `SeedPgpPlaintext` object ## Testing ```bash # Run all tests bun test # Run with verbose output bun test --verbose # Watch mode (auto-rerun on changes) bun test --watch ``` ### Test Coverage - โœ… 15 comprehensive tests - โœ… 8 official Trezor BIP39 test vectors - โœ… Edge cases (wrong key, wrong passphrase) - โœ… Frame format validation - โœ… CRC16 integrity checking ## Security Considerations ### โœ… Best Practices - Uses **AES-256** for symmetric encryption - **cv25519** provides ~128-bit security level - **CRC16** detects QR scan errors (not cryptographic) - Key fingerprint validation prevents wrong-key usage ### โš ๏ธ Important Notes - **Never share your private key or encrypted QR codes publicly** - Store backup QR codes in secure physical locations (safe, safety deposit box) - Use a strong PGP key passphrase (20+ characters) - Test decryption immediately after generating backups - Consider password-only (SKESK) encryption as additional fallback ## Project Structure ``` seedpgp-web/ โ”œโ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ 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 โ”œโ”€โ”€ package.json โ””โ”€โ”€ README.md ``` ## Tech Stack - **Runtime**: [Bun](https://bun.sh) v1.3.6+ - **Language**: TypeScript - **Crypto**: [OpenPGP.js](https://openpgpjs.org) v6.3.0 - **Framework**: React + Vite - **Testing**: Bun test runner ## Roadmap - [ ] QR code generation UI - [ ] Multi-frame support for larger payloads - [ ] Hardware wallet integration - [ ] Mobile scanning app - [ ] Shamir Secret Sharing support ## License MIT License - see LICENSE file for details ## Author **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 --- โš ๏ธ **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. ```