add wheels and update docs

This commit is contained in:
LC mac
2026-01-09 19:16:28 +08:00
parent 6457ec2cee
commit 2f7433b704
5 changed files with 180 additions and 3 deletions

View File

@@ -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)
---

View File

@@ -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).