# pyhdwallet v1.0.5 A secure, offline-first command-line tool for generating and recovering BIP39 HD wallets with support for Ethereum, Solana, and Bitcoin. It supports optional PGP-encrypted payloads (ASCII-armored `.asc`) and deterministic AES-encrypted ZIP wallet artifacts written under a local `.wallet/` folder. ## Purpose pyhdwallet helps create new wallets or recover from existing mnemonics/seeds with offline operation, auditable derivation, and optional encryption for safer storage. PGP encryption produces an ASCII-armored PGP message suitable for saving as `.asc`.[3] ## Repository layout - `src/pyhdwallet.py` — main CLI script - `.wallet/` — generated wallet artifacts (recommend adding to `.gitignore`) - `requirements.in`, `requirements.txt` - `README.md`, `playbook.md`, `LICENSE` ## Installation 1. Ensure Python 3.11+ is installed. 1. Clone/download the repo. 1. Create and activate a virtual environment: ```bash python -m venv .venv source .venv/bin/activate ``` 1. Install dependencies: ```bash python -m pip install -r requirements.txt ``` ## Basic usage Run the tool with a subcommand. For help, use `-h` (e.g., `gen -h`, `recover -h`). ```bash # Generate (prints mnemonic by default; intended for debug/test) python ./src/pyhdwallet.py gen # Generate and save an AES-encrypted ZIP artifact into ./.wallet (password prompted) python ./src/pyhdwallet.py gen --file # Generate with PGP encryption + ZIP artifact (ZIP contains only encrypted .asc payload) python ./src/pyhdwallet.py gen --pgp-pubkey-file pubkeys/mykey.asc --file # Recover from mnemonic (prefer --interactive to avoid shell history) python ./src/pyhdwallet.py recover --interactive # Recover and save AES ZIP artifact python ./src/pyhdwallet.py recover --interactive --file # Fetch PGP public key (online) python ./src/pyhdwallet.py fetchkey "https://example.com/key.asc" --out mykey.asc # Run tests python ./src/pyhdwallet.py test ``` ## Notes on `--file`, AES ZIP, and PGP - `--file` writes **only** an AES-encrypted ZIP (no raw `.json`/`.asc` is left on disk), using `pyzipper`.[4] - If `--pgp-pubkey-file` is set, the ZIP contains a single ASCII-armored PGP message (`.asc`) created with PGPy-style `PGPMessage.new(...)` then `pubkey.encrypt(...)`.[3] ## About `--force` The tool includes a safety guard: if stdout is piped/redirected (non-TTY), it refuses to print sensitive output unless `--force` is set. Checking whether stdout is a terminal is commonly done via `isatty()`. Example: ```bash python ./src/pyhdwallet.py gen > out.txt # likely refused (non-TTY) python ./src/pyhdwallet.py gen --force > out.txt # forced (dangerous) ``` ## Security - Designed to run offline; `gen`, `recover`, and `test` block network access in-process. - Use `--off-screen` to suppress printing sensitive data to stdout. - Prefer `--file` (AES ZIP) and optionally combine with `--pgp-pubkey-file` for stronger at-rest security. - For detailed examples and operational guidance, see `playbook.md`.