add wheels and update docs
This commit is contained in:
35
README.md
35
README.md
@@ -1,6 +1,6 @@
|
||||
# pyhdwallet – Secure HD Wallet Tool
|
||||
|
||||
A Python command-line tool for generating and recovering BIP39 HD wallets with support for Ethereum, Solana, and Bitcoin. Designed for offline operation with optional PGP encryption and AES-encrypted ZIP artifacts.
|
||||
A Python command-line tool for generating and recovering BIP39 HD wallets with support for Ethereum, Solana, and Bitcoin. Includes **BIP85 deterministic child mnemonic derivation** for creating multiple isolated wallets from a single master seed. Designed for offline operation with optional PGP encryption and AES-encrypted ZIP artifacts.
|
||||
|
||||
---
|
||||
|
||||
@@ -32,7 +32,7 @@ This repository includes pre-built Python wheels for offline use.
|
||||
|
||||
**Supported platforms:**
|
||||
|
||||
- macOS ARM64 (M1/M2/M3) - Python 3.12
|
||||
- macOS ARM64 (M1/M2/M3/M4) - Python 3.12
|
||||
- Linux x86_64 (Ubuntu/Tails) - Python 3.12
|
||||
|
||||
**Steps:**
|
||||
@@ -102,6 +102,22 @@ python src/pyhdwallet.py gen \
|
||||
--off-screen \
|
||||
--file
|
||||
|
||||
# Derive BIP85 child mnemonic (12/15/18/21/24 words)
|
||||
python src/pyhdwallet.py gen-child \
|
||||
--interactive \
|
||||
--words 12 \
|
||||
--index 0
|
||||
|
||||
# Derive BIP85 child with passphrase + encrypted output
|
||||
python src/pyhdwallet.py gen-child \
|
||||
--mnemonic-stdin \
|
||||
--passphrase \
|
||||
--words 24 \
|
||||
--index 0 \
|
||||
--pgp-pubkey-file pubkeys/mykey.asc \
|
||||
--off-screen \
|
||||
--file
|
||||
|
||||
# Recover wallet from mnemonic
|
||||
python src/pyhdwallet.py recover --interactive --file
|
||||
|
||||
@@ -118,11 +134,13 @@ pytest -v tests/test_vectors.py
|
||||
## 🔐 Security Features
|
||||
|
||||
- **Offline-first**: Network access blocked during key generation/recovery
|
||||
- **BIP85 deterministic entropy**: Derive unlimited child mnemonics from master seed
|
||||
- **Test suite**: Regression tests with frozen vectors ensure derivation logic integrity
|
||||
- **PGP fingerprint pinning**: Prevents key substitution attacks
|
||||
- **TTY safety guard**: Refuses to print secrets when stdout is piped/redirected
|
||||
- **AES-encrypted outputs**: Wallet artifacts encrypted with `pyzipper`
|
||||
- **No shell history leaks**: Use `--interactive` or `--mnemonic-stdin` for recovery
|
||||
- **Interoperable**: BIP85 children compatible with Coldcard, Ian Coleman tool, etc.
|
||||
|
||||
---
|
||||
|
||||
@@ -170,3 +188,16 @@ For maximum security when generating production wallets:
|
||||
8. Wipe USB drives securely
|
||||
|
||||
See [playbook.md](playbook.md) for detailed air-gapped procedures.
|
||||
|
||||
---
|
||||
|
||||
## 🆕 What's New in v1.0.6
|
||||
|
||||
- **BIP85 child mnemonic derivation** via new `gen-child` command
|
||||
- Derive 12/15/18/21/24-word child mnemonics from master seed
|
||||
- Full interoperability with BIP85-compatible wallets (Coldcard, etc.)
|
||||
- Optional master BIP39 passphrase support
|
||||
- Verified against official BIP85 test vectors
|
||||
- No new dependencies required (uses existing bip-utils + stdlib)
|
||||
|
||||
---
|
||||
|
||||
148
playbook.md
148
playbook.md
@@ -186,7 +186,8 @@ The project includes a comprehensive offline test suite that validates critical
|
||||
- **PGP fingerprint calculation**: Verifies that PGP key fingerprinting logic produces expected results and enforces fingerprint matching
|
||||
- **BIP39 seed derivation**: Ensures mnemonics (with and without passphrases) always produce the same seed hex
|
||||
- **Multi-chain address derivation**: Validates Ethereum, Bitcoin (3 address types), and Solana (3 profiles) derivation paths remain stable
|
||||
- **CLI integration**: Smoke tests for `recover` command with correct and incorrect fingerprints
|
||||
- **BIP85 child mnemonic derivation**: Verifies BIP85 entropy generation, path construction, and child mnemonic output against official test vectors
|
||||
- **CLI integration**: Smoke tests for `recover` and `gen-child` commands with correct and incorrect fingerprints
|
||||
|
||||
#### Running Tests
|
||||
|
||||
@@ -325,6 +326,141 @@ Naming uses UTC timestamps (e.g. `20260108_011830Z`):
|
||||
|
||||
## Commands
|
||||
|
||||
### gen-child (offline) - **NEW in v1.0.6**
|
||||
|
||||
Derive a child BIP39 mnemonic from a master mnemonic using BIP85 deterministic entropy.
|
||||
|
||||
**What is BIP85?**
|
||||
|
||||
BIP85 allows you to derive unlimited child mnemonics from a single master seed. Each child mnemonic is:
|
||||
|
||||
- **Deterministic**: Same master + index always produces the same child
|
||||
- **Isolated**: Compromise of one child doesn't affect others or the master
|
||||
- **Interoperable**: Works with Coldcard, Ian Coleman tool, and other BIP85-compatible wallets
|
||||
- **Portable**: Transfer child mnemonics to hot wallets without exposing your master seed
|
||||
|
||||
**Use cases:**
|
||||
|
||||
- Generate separate wallets for different exchanges/services
|
||||
- Create disposable wallets for testing
|
||||
- Delegate wallets to family members or business partners
|
||||
- Maintain one master backup while having multiple operational wallets
|
||||
|
||||
```bash
|
||||
python ./src/pyhdwallet.py gen-child [options]
|
||||
```
|
||||
|
||||
**Input options (choose one - required):**
|
||||
|
||||
- `--interactive` — Word-by-word guided master mnemonic entry (English-only, per-word validation)
|
||||
- `--mnemonic-stdin` — Read master mnemonic from stdin (recommended; avoids shell history)
|
||||
|
||||
**Child parameters:**
|
||||
|
||||
- `--words {12,15,18,21,24}` — Child mnemonic word count (default: 12)
|
||||
- `--index N` — BIP85 derivation index (default: 0; use different indexes for different children)
|
||||
- `--passphrase` — Prompt for master BIP39 passphrase (optional but recommended if your master uses one)
|
||||
- `--passphrase-hint HINT` — Store hint only (requires `--passphrase`)
|
||||
|
||||
**Output options:**
|
||||
|
||||
- `--off-screen` — Suppress printing child mnemonic to stdout (prints metadata only)
|
||||
- `--force` — Allow printing to non-TTY stdout (dangerous; see security notes)
|
||||
|
||||
**File output options:**
|
||||
|
||||
- `--file` — Write AES-encrypted ZIP artifact to `.wallet/` (or `--wallet-location`)
|
||||
- `--pgp-pubkey-file FILE` — PGP-encrypt the inner JSON payload
|
||||
- `--expected-fingerprint FINGERPRINT` — Enforce PGP key pinning
|
||||
- `--wallet-location PATH` — Override default `.wallet/` directory
|
||||
- `--zip-password-mode {prompt,auto}` — ZIP password entry mode
|
||||
- `--zip-password-len N` — Auto-generated password length (default: 12)
|
||||
- `--show-generated-password` — Print auto-generated ZIP password to stderr
|
||||
|
||||
**BIP85 Derivation Path:**
|
||||
|
||||
The tool uses the standard BIP85 path for BIP39 application:
|
||||
|
||||
```
|
||||
m/83696968'/39'/0'/{words}'/{index}'
|
||||
```
|
||||
|
||||
- `83696968'` — BIP85 magic constant
|
||||
- `39'` — BIP39 application
|
||||
- `0'` — English language (only supported language in v1.0.6)
|
||||
- `{words}'` — Child mnemonic word count (12/15/18/21/24)
|
||||
- `{index}'` — Your chosen index
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# 1. Basic: Derive 12-word child at index 0 (interactive entry)
|
||||
python src/pyhdwallet.py gen-child --interactive --words 12 --index 0
|
||||
|
||||
# 2. Derive 24-word child with passphrase (from stdin)
|
||||
echo "your master mnemonic words here" | \
|
||||
python src/pyhdwallet.py gen-child \
|
||||
--mnemonic-stdin \
|
||||
--passphrase \
|
||||
--words 24 \
|
||||
--index 0
|
||||
|
||||
# 3. Secure: Off-screen + PGP encryption + ZIP file
|
||||
python src/pyhdwallet.py gen-child \
|
||||
--interactive \
|
||||
--words 12 \
|
||||
--index 1 \
|
||||
--pgp-pubkey-file pubkeys/recipient.asc \
|
||||
--expected-fingerprint A27B96F2B169B5491013D2DA892B822C14A9AA18 \
|
||||
--off-screen \
|
||||
--file
|
||||
|
||||
# 4. Multiple children: Derive index 0, 1, 2 for different purposes
|
||||
for i in 0 1 2; do
|
||||
echo "master mnemonic" | python src/pyhdwallet.py gen-child \
|
||||
--mnemonic-stdin --words 12 --index $i --off-screen --file
|
||||
done
|
||||
```
|
||||
|
||||
**Security Notes:**
|
||||
|
||||
- **Master seed safety**: Never expose your master mnemonic to online systems. Use `gen-child` only on air-gapped machines.
|
||||
- **Index tracking**: Keep a record of which index corresponds to which purpose (e.g., index 0 = exchange A, index 1 = exchange B).
|
||||
- **Passphrase consistency**: If your master seed uses a BIP39 passphrase, you MUST provide the same passphrase when deriving children.
|
||||
- **Interoperability verification**: Always test child mnemonics in a separate wallet before sending funds to ensure compatibility.
|
||||
|
||||
**Interoperability:**
|
||||
|
||||
This implementation follows BIP85 specification and has been verified against official test vectors. Child mnemonics are compatible with:
|
||||
|
||||
- Coldcard hardware wallet (BIP85 menu)
|
||||
- Ian Coleman BIP85 calculator ([https://iancoleman.io/bip39/](https://iancoleman.io/bip39/))
|
||||
- Trezor (when BIP85 support is added)
|
||||
- Any other BIP85-compliant tool
|
||||
|
||||
**Output Payload Structure:**
|
||||
|
||||
When using `--file`, the encrypted ZIP contains a JSON payload with:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "pyhdwallet v1.0.6",
|
||||
"purpose": "BIP85 derived child mnemonic",
|
||||
"master_fingerprint": "ABCD1234",
|
||||
"master_word_count": 24,
|
||||
"passphrase_used": true,
|
||||
"passphrase_hint": "my hint",
|
||||
"bip85_metadata": {
|
||||
"path": "m/83696968'/39'/0'/12'/0'",
|
||||
"index": 0,
|
||||
"language": 0,
|
||||
"child_word_count": 12
|
||||
},
|
||||
"child_mnemonic": "word1 word2 ...",
|
||||
"interoperability_note": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### fetchkey (online)
|
||||
|
||||
Download and verify a PGP public key from a URL.
|
||||
@@ -759,6 +895,16 @@ python src/pyhdwallet.py test
|
||||
|
||||
## Changelog
|
||||
|
||||
- **v1.0.6** (2026-01-09)
|
||||
- **Added**: BIP85 child mnemonic derivation via new `gen-child` command
|
||||
- Supports deriving 12/15/18/21/24-word children from master seed
|
||||
- Optional master BIP39 passphrase support
|
||||
- Full interoperability with BIP85-compatible wallets (Coldcard, Ian Coleman tool)
|
||||
- Verified against official BIP85 test vectors
|
||||
- Added BIP85 regression tests to test suite
|
||||
- No new dependencies required (uses existing `bip-utils` + stdlib)
|
||||
- BIP85 path: `m/83696968'/39'/0'/{words}'/{index}'`
|
||||
|
||||
- **v1.0.5**
|
||||
- `--unsafe-print` removed; `gen` prints mnemonic by default (debug/test behavior).
|
||||
- `--output` removed; file payload is always JSON (unencrypted) or `.asc` (PGP encrypted).
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user