From ccd070dc56146cb27a51d7ea6b99d8fd36179a0d Mon Sep 17 00:00:00 2001 From: LC mac Date: Wed, 7 Jan 2026 00:53:39 +0800 Subject: [PATCH] modified README --- README.md | 82 ++++++++++++++++++++++++++++++++++++++++++----------- playbook.md | 24 ++++++++-------- 2 files changed, 78 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7a02398..a6c0fdd 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,81 @@ -# pyhdwallet v1.0.4 +# pyhdwallet v1.0.5 -A secure, offline command-line tool for generating and recovering BIP39 HD wallets with support for Ethereum, Solana, and Bitcoin. +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 you create new wallets or recover from existing mnemonics/seeds, with built-in PGP encryption for secure storage. It's designed for privacy-conscious users who want offline, auditable wallet management. +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. -2. Clone/download the repo. -3. Create a virtual environment: `python -m venv .venv && source .venv/bin/activate` -4. Install dependencies: `pip install -r requirements.txt` +1. Clone/download the repo. +1. Create and activate a virtual environment: -## Basic Usage +```bash +python -m venv .venv +source .venv/bin/activate +``` -Run the tool with a subcommand. For help, use `-h`. +1. Install dependencies: -- Generate a wallet: `python ./src/pyhdwallet.py gen --chains ethereum --addresses 3` -- Recover from mnemonic: `python ./src/pyhdwallet.py recover --mnemonic "your words" --chains bitcoin` -- Fetch PGP key: `python ./src/pyhdwallet.py fetchkey "https://example.com/key.asc"` -- Run tests: `python ./src/pyhdwallet.py test` +```bash +python -m pip install -r requirements.txt +``` -For detailed examples and security tips, see `playbook.md`. +## 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 -- Operates offline by default. -- Use `--off-screen` for high-security operations. -- Always verify PGP keys and run on trusted systems. +- 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`. diff --git a/playbook.md b/playbook.md index 18ee3cb..338a370 100644 --- a/playbook.md +++ b/playbook.md @@ -17,8 +17,8 @@ Repository structure (current): - **Offline-first**: `gen`, `recover`, and `test` block network access (best-effort in-process guard). - **Multi-chain support**: Derives addresses for Ethereum, Solana, and Bitcoin. -- **PGP encryption**: Encrypts a JSON payload to a PGP public key and outputs an ASCII-armored PGP message (typically saved as `.asc`). [web:46] -- **AES-encrypted ZIP artifacts**: When `--file` is used, output is written as an AES-encrypted ZIP via `pyzipper`. [web:102] +- **PGP encryption**: Encrypts a JSON payload to a PGP public key and outputs an ASCII-armored PGP message (typically saved as `.asc`). +- **AES-encrypted ZIP artifacts**: When `--file` is used, output is written as an AES-encrypted ZIP via `pyzipper`. - **TTY safety guard + --force**: If stdout is piped/redirected (non-TTY), the tool refuses to print sensitive data unless `--force` is explicitly set (to avoid accidental leaks into logs/files). `isatty()` is the classic way to detect whether stdout is connected to a terminal. - **Off-screen mode**: `--off-screen` suppresses printing sensitive data to stdout. @@ -42,9 +42,9 @@ python -m pip install -r requirements.txt ### Dependencies (top-level intent) - `bip-utils` — BIP39 + BIP derivation logic -- `PGPy` — encryption to OpenPGP public keys [web:46] +- `PGPy` — encryption to OpenPGP public keys - `pynacl` + `base58` — Solana seed/key handling -- `pyzipper` — AES-encrypted ZIP writing (only needed when using `--file`) [web:102] +- `pyzipper` — AES-encrypted ZIP writing (only needed when using `--file`) --- @@ -97,7 +97,7 @@ python ./src/pyhdwallet.py test ### `--file` behavior (deterministic, secured output) -If `--file` is present, the tool writes **only** an AES-encrypted ZIP file (no raw `.json`/`.asc` file is left on disk). AES ZIP is implemented using `pyzipper`. [web:102] +If `--file` is present, the tool writes **only** an AES-encrypted ZIP file (no raw `.json`/`.asc` file is left on disk). AES ZIP is implemented using `pyzipper`. Default output folder: @@ -119,7 +119,7 @@ Naming uses UTC timestamps (e.g. `20260106_161830Z`): - Optional: `--zip-password-mode auto` generates a Base58 password (length controlled by `--zip-password-len`). - If auto mode is used, password is shown **only if** `--show-generated-password` is set, and it prints to **stderr** (not stdout) to reduce accidental capture when stdout is redirected. -`pyzipper` supports AES encryption via `AESZipFile` and password-setting APIs. [web:102] +`pyzipper` supports AES encryption via `AESZipFile` and password-setting APIs. --- @@ -162,7 +162,7 @@ Core options: PGP options: -- `--pgp-pubkey-file FILE` (encrypt payload to pubkey; `.asc` content) [web:46] +- `--pgp-pubkey-file FILE` (encrypt payload to pubkey; `.asc` content) - `--pgp-ignore-usage-flags` Artifact options: @@ -243,8 +243,8 @@ If running normally in your interactive terminal, stdout is a TTY and `--force` - `gen` printing the mnemonic is intentionally “debug/test” behavior. Assume stdout can be recorded (scrollback, logging, screen recording, CI logs). - Prefer `--off-screen` for reduced exposure. -- Prefer `--file` so artifacts go into `.wallet/` and are AES-encrypted via `pyzipper`. [web:102] -- For stronger at-rest security: combine `--pgp-pubkey-file` + `--file` so the ZIP contains only an encrypted `.asc` payload. PGPy encryption style follows `PGPMessage.new(...)` then `pubkey.encrypt(...)`. [web:46] +- Prefer `--file` so artifacts go into `.wallet/` and are AES-encrypted via `pyzipper`. +- For stronger at-rest security: combine `--pgp-pubkey-file` + `--file` so the ZIP contains only an encrypted `.asc` payload. PGPy encryption style follows `PGPMessage.new(...)` then `pubkey.encrypt(...)`. --- @@ -287,7 +287,7 @@ print("Extracted to", out_dir) PY ``` -AES ZIP support is the reason `pyzipper` is used. [web:102] +AES ZIP support is the reason `pyzipper` is used. --- @@ -295,8 +295,8 @@ AES ZIP support is the reason `pyzipper` is used. [web:102] - **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). [web:46] - - `--file` is now a boolean flag that writes **only** AES-encrypted ZIP artifacts (no raw output files). [web:102] + - `--output` removed; file payload is always JSON (unencrypted) or `.asc` (PGP encrypted). + - `--file` is now a boolean flag that writes **only** AES-encrypted ZIP artifacts (no raw output files). - Added: `--wallet-location`, `--zip-password-mode`, `--zip-password-len`, `--show-generated-password`. - Added: `--force` to override the non-TTY printing safety guard (use only when redirecting/piping).