174 lines
6.3 KiB
Markdown
174 lines
6.3 KiB
Markdown
Below is a practical playbook you can save as `PLAYBOOK.md` next to `hdwallet_recovery.py`.
|
||
|
||
## Purpose (what this tool does)
|
||
- **Derive addresses** (ETH/SOL/BTC) from either a BIP39 mnemonic (+ optional passphrase) or a raw 64‑byte BIP39 seed hex.
|
||
- Optionally **encrypt a payload** to a PGP public key (ASCII armored) so secrets are not shown in plaintext on screen.
|
||
- `fetchkey` mode is the only mode that touches the network (downloads a PGP public key).
|
||
|
||
## Prerequisites (software + packages)
|
||
|
||
### OS / Python
|
||
- Use **Python 3.12** (recommended for compatibility with `bip_utils`, `PGPy`, etc.).
|
||
- macOS: install Python 3.12 via Homebrew and create a clean venv.
|
||
|
||
### Python packages
|
||
Install into a venv:
|
||
|
||
**Base (derive addresses + encrypt payload):**
|
||
- `bip-utils`
|
||
- `PGPy`
|
||
|
||
**Only needed if you use `--export-private` and include `solana`:**
|
||
- `PyNaCl`
|
||
- `base58`
|
||
|
||
Example:
|
||
```bash
|
||
python -m venv .venv
|
||
source .venv/bin/activate
|
||
pip install -U pip
|
||
pip install bip-utils PGPy
|
||
pip install PyNaCl base58 # only if exporting Solana private keys
|
||
```
|
||
|
||
## Files you need
|
||
- `hdwallet_recovery.py` (the script)
|
||
- `kccleoc.asc` (or any `*.asc`) = ASCII-armored **PGP public key** used to encrypt the payload
|
||
|
||
## Operating modes
|
||
|
||
### Mode A — fetchkey (online, no secrets allowed)
|
||
Use this to download a PGP public key from a URL and verify it.
|
||
|
||
**Command:**
|
||
```bash
|
||
python hdwallet_recovery.py fetchkey "https://github.com/<user>.gpg" --out key.asc
|
||
```
|
||
|
||
**What to check:**
|
||
- The script prints **SHA256** of the downloaded key and the **PGP fingerprint**.
|
||
- Independently verify the fingerprint matches the intended owner (don’t trust only the URL).
|
||
|
||
**Safety rule:**
|
||
- Never pass mnemonic/seed/passphrase flags together with `fetchkey`. The script should refuse.
|
||
|
||
***
|
||
|
||
### Mode B — derive (offline, addresses only)
|
||
Derives addresses and prints them to stdout.
|
||
|
||
**Command (addresses only):**
|
||
```bash
|
||
python hdwallet_recovery.py \
|
||
--mnemonic '... your words ...' \
|
||
--passphrase '' \
|
||
--chains ethereum solana bitcoin \
|
||
--addresses 10
|
||
```
|
||
|
||
**Notes:**
|
||
- This prints addresses (safe) but still requires you to supply the mnemonic (sensitive) on the command line unless you use `--interactive`.
|
||
|
||
**Preferred (avoid shell history):**
|
||
```bash
|
||
python hdwallet_recovery.py --interactive --chains ethereum solana bitcoin --addresses 10
|
||
```
|
||
|
||
***
|
||
|
||
### Mode C — derive + PGP encrypt payload (recommended)
|
||
Derives addresses, prints addresses, and prints an **encrypted PGP block** containing recovery material.
|
||
|
||
**Command (include mnemonic + passphrase):**
|
||
```bash
|
||
python hdwallet_recovery.py \
|
||
--interactive \
|
||
--chains ethereum solana bitcoin \
|
||
--addresses 10 \
|
||
--pgp-pubkey-file key.asc
|
||
```
|
||
|
||
**Decrypt later:**
|
||
- Use your PGP private key (on a safe machine) to decrypt the PGP message.
|
||
|
||
***
|
||
|
||
### Mode D — derive + export private keys (encrypted only)
|
||
This is for when you need to import per-account keys into hot wallets (e.g., Phantom) but **don’t want to type the seed phrase into the app**.
|
||
|
||
**Behavior (as implemented):**
|
||
- Still prints addresses to stdout.
|
||
- Produces a PGP-encrypted payload that includes:
|
||
- the mnemonic (so you can fully recover later)
|
||
- a note that a passphrase was used (but not the passphrase)
|
||
- **Ethereum private keys** (hex) for indices `0..--addresses-1`
|
||
- **Solana Phantom-compatible private keys** (base58 64-byte secret key) for indices `0..--addresses-1`
|
||
- **Bitcoin: addresses only** (no BTC private keys)
|
||
|
||
**Command:**
|
||
```bash
|
||
python hdwallet_recovery.py \
|
||
--interactive \
|
||
--chains ethereum solana bitcoin \
|
||
--addresses 10 \
|
||
--export-private \
|
||
--passphrase 'YOUR_PASSPHRASE' \
|
||
--passphrase-hint 'memory hint here' \
|
||
--pgp-pubkey-file key.asc
|
||
```
|
||
|
||
**Hot wallet import guidance:**
|
||
- Import only the specific derived account key you plan to treat as “hot”.
|
||
- Fund only that account/address.
|
||
- Assume the device/app is compromised eventually; rotate keys.
|
||
|
||
## Verification checklist (before trusting results)
|
||
- Confirm you’re using the expected Python and venv:
|
||
```bash
|
||
which python
|
||
python -V
|
||
pip show bip-utils PGPy
|
||
```
|
||
- Confirm the PGP public key fingerprint is correct (out-of-band verified).
|
||
- Confirm derived addresses match known wallet UI for the same mnemonic/passphrase (test with a small index range first).
|
||
|
||
## Security warnings (read this every time)
|
||
- **Never** run derive mode on a machine you don’t trust.
|
||
- Avoid passing mnemonics on the command line (`--mnemonic '...'`) because:
|
||
- shell history may capture it
|
||
- process lists can expose arguments
|
||
- Prefer `--interactive` so the mnemonic is hidden input.
|
||
- The encrypted payload printed to screen can still be:
|
||
- copied into scrollback logs
|
||
- captured by screen recording / monitoring
|
||
- saved by terminal multiplexer logs
|
||
Treat it as sensitive, even if encrypted.
|
||
- If `--export-private` is used, the encrypted payload contains a **bundle of hot private keys**. Anyone who decrypts it controls those accounts. Keep it offline and limit distribution.
|
||
- If a **passphrase** was used, losing it makes recovery impossible even with mnemonic and derived-address list. Store the passphrase separately and securely; the payload only stores a hint/reminder.
|
||
- Consider using a dedicated “hot” seed (separate mnemonic) for accounts intended for hot-wallet import, rather than exporting keys derived from your main long-term seed.
|
||
|
||
## Quick command recipes
|
||
|
||
**1) Download and pin a key:**
|
||
```bash
|
||
python hdwallet_recovery.py fetchkey "https://github.com/<user>.gpg" --out key.asc
|
||
```
|
||
|
||
**2) Offline derive addresses (no encryption):**
|
||
```bash
|
||
python hdwallet_recovery.py --interactive --chains ethereum solana bitcoin --addresses 10
|
||
```
|
||
|
||
**3) Offline derive + encrypt payload (no private key export):**
|
||
```bash
|
||
python hdwallet_recovery.py --interactive --chains ethereum solana bitcoin --addresses 10 --pgp-pubkey-file key.asc
|
||
```
|
||
|
||
**4) Offline derive + encrypt payload + export ETH/SOL private keys:**
|
||
```bash
|
||
python hdwallet_recovery.py --interactive --chains ethereum solana bitcoin --addresses 10 --export-private --passphrase-hint '...' --pgp-pubkey-file key.asc
|
||
```
|
||
|
||
If you want, the playbook can be turned into a `Makefile` (targets: `venv`, `fetchkey`, `derive`, `export`) so you don’t have to remember flags.
|
||
|
||
[1](https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/50321846/61044779-f904-4af9-9005-77f3f639e4d6/offline_HD_wallet_generator.html) |