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.txtREADME.md,playbook.md,LICENSE
Installation
- Ensure Python 3.11+ is installed.
- Clone/download the repo.
- Create and activate a virtual environment:
python -m venv .venv
source .venv/bin/activate
- Install dependencies:
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).
# 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
--filewrites only an AES-encrypted ZIP (no raw.json/.ascis left on disk), usingpyzipper.[4]- If
--pgp-pubkey-fileis set, the ZIP contains a single ASCII-armored PGP message (.asc) created with PGPy-stylePGPMessage.new(...)thenpubkey.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:
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, andtestblock network access in-process. - Use
--off-screento suppress printing sensitive data to stdout. - Prefer
--file(AES ZIP) and optionally combine with--pgp-pubkey-filefor stronger at-rest security. - For detailed examples and operational guidance, see
playbook.md.