add BestPractices.md
This commit is contained in:
174
BestPractices.md
Normal file
174
BestPractices.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Offline Security Best Practices
|
||||
|
||||
This tool is designed for offline use, but true security depends on the **environment** where you run it. Below are operational security recommendations for generating keys you can trust.
|
||||
|
||||
## Air-Gapped Setup (Highest Security)
|
||||
|
||||
For maximum security when generating production wallets, use an **air-gapped computer**—a device that has never been and will never be connected to any network.
|
||||
|
||||
**Recommended procedure:**
|
||||
|
||||
1. **Prepare a clean machine**:
|
||||
- Use a dedicated laptop or bootable USB with a fresh Linux installation (e.g., Tails, Ubuntu Live USB)
|
||||
- Never connect this device to WiFi, Ethernet, or Bluetooth [web:14]
|
||||
- Physically disable network interfaces if possible (remove WiFi card, tape over Ethernet port)
|
||||
|
||||
2. **Transfer dependencies offline**:
|
||||
|
||||
```bash
|
||||
# On an online machine, download dependencies
|
||||
pip download -r requirements.txt -d ./offline-deps
|
||||
|
||||
# Transfer ./offline-deps to air-gapped machine via USB
|
||||
# On air-gapped machine:
|
||||
pip install --no-index --find-links=./offline-deps -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Verify code integrity**:
|
||||
- Check the git commit hash matches the version you reviewed
|
||||
- Optionally run `pytest -v tests/test_vectors.py` on the air-gapped machine to verify derivation logic
|
||||
|
||||
4. **Generate wallet**:
|
||||
|
||||
```bash
|
||||
python ./src/pyhdwallet.py gen --pgp-pubkey-file pubkeys/recipient.asc --file --off-screen
|
||||
```
|
||||
|
||||
5. **Transfer output safely**:
|
||||
- Copy only the `.wallet/*.zip` file to USB (never copy `pyhdwallet.py` or Python environment back to online machine)
|
||||
- The ZIP is AES-encrypted; the inner `.asc` is PGP-encrypted [web:19]
|
||||
|
||||
6. **Destroy or securely wipe** the USB after transfer if it contained unencrypted secrets
|
||||
|
||||
### Threats Air-Gapping Mitigates
|
||||
|
||||
- **Remote attacks**: Malware cannot exfiltrate keys over the network
|
||||
- **Clipboard hijacking**: No clipboard manager or remote access tool can intercept data
|
||||
- **Browser/OS telemetry**: No accidental upload of terminal history or crash dumps
|
||||
|
||||
### Threats Air-Gapping Does NOT Fully Mitigate
|
||||
|
||||
Research shows that sophisticated attackers with physical access can potentially exfiltrate data from air-gapped systems via covert channels (acoustic, electromagnetic, optical) [web:18]. However:
|
||||
|
||||
- These attacks require physical proximity and pre-installed malware [web:18]
|
||||
- For individual users (not nation-state targets), air-gapping remains highly effective
|
||||
- Countermeasures: Use the machine in a secure location, inspect for unfamiliar USB devices, verify software integrity before installation [web:18]
|
||||
|
||||
### Physical Security
|
||||
|
||||
**Mnemonic handling:**
|
||||
|
||||
- Write the mnemonic on paper immediately; never store it digitally on the air-gapped machine
|
||||
- Use a metal backup (e.g., Cryptosteel) for fire/water resistance
|
||||
- Split storage across multiple secure locations if desired (Shamir's Secret Sharing for advanced users)
|
||||
|
||||
**Device handling:**
|
||||
|
||||
- After generating the wallet, optionally wipe the air-gapped device or destroy the bootable USB
|
||||
- If reusing the device, use secure-erase tools (not just `rm`)
|
||||
|
||||
### Verification Through Testing
|
||||
|
||||
**Why the test suite matters for trust:**
|
||||
|
||||
The committed test suite (`tests/test_vectors.py`) allows you to verify that derivation logic hasn't been tampered with before generating production keys:
|
||||
|
||||
```bash
|
||||
# On the air-gapped machine, before generating your wallet:
|
||||
pytest -v tests/test_vectors.py
|
||||
```
|
||||
|
||||
If all tests pass, you have cryptographic proof that:
|
||||
|
||||
- BIP39 seed derivation matches the well-known test vector ("abandon abandon..." → known seed) [file:2]
|
||||
- Derivation paths produce addresses matching public BIP39/BIP44 test vectors
|
||||
- PGP fingerprinting logic works correctly
|
||||
|
||||
If tests fail, **do not generate keys**—the code may be compromised or buggy.
|
||||
|
||||
### Entropy Sources
|
||||
|
||||
**Built-in entropy (default):**
|
||||
|
||||
- Python's `secrets.token_bytes()` uses OS-provided CSPRNG (`/dev/urandom` on Linux, `CryptGenRandom` on Windows)
|
||||
- This is cryptographically secure for typical use
|
||||
|
||||
**Additional user entropy (optional):**
|
||||
|
||||
```bash
|
||||
python ./src/pyhdwallet.py gen --dice-rolls "4 2 6 1 3 5 ..." --file
|
||||
```
|
||||
|
||||
- Roll a die 50+ times and input the results
|
||||
- Your dice rolls are mixed with OS entropy via SHA256 [file:2]
|
||||
- Protects against potential CSPRNG backdoors (theoretical concern)
|
||||
|
||||
### PGP Key Fingerprint Pinning
|
||||
|
||||
Always use `--expected-fingerprint` when encrypting to a PGP key to prevent key substitution attacks [file:2]:
|
||||
|
||||
```bash
|
||||
# First, get and verify the fingerprint of your recipient key
|
||||
python ./src/pyhdwallet.py fetchkey https://example.com/mykey.asc --out mykey.asc
|
||||
# Manually verify fingerprint matches what you expect (check via another channel)
|
||||
|
||||
# Then use it with pinning:
|
||||
python ./src/pyhdwallet.py gen \
|
||||
--pgp-pubkey-file mykey.asc \
|
||||
--expected-fingerprint A27B96F2B169B5491013D2DA892B822C14A9AA18 \
|
||||
--file
|
||||
```
|
||||
|
||||
Without `--expected-fingerprint`, an attacker who controls the filesystem could swap `mykey.asc` with their own key.
|
||||
|
||||
### Operational Checklist
|
||||
|
||||
Before generating production wallets:
|
||||
|
||||
- [ ] Running on air-gapped machine or fresh Live USB
|
||||
- [ ] Network physically disabled (no WiFi/Ethernet/Bluetooth)
|
||||
- [ ] Code integrity verified (git commit hash + test suite passes)
|
||||
- [ ] Using `--off-screen` to minimize terminal scrollback exposure
|
||||
- [ ] Using `--file` to avoid leaving unencrypted files on disk
|
||||
- [ ] Using `--pgp-pubkey-file` with `--expected-fingerprint` for key pinning
|
||||
- [ ] Paper/metal backup prepared for mnemonic
|
||||
- [ ] Output ZIP password stored separately from ZIP file
|
||||
- [ ] Plan for USB secure wipe after transfer
|
||||
|
||||
### Lower-Risk Scenarios
|
||||
|
||||
Air-gapping is overkill for:
|
||||
|
||||
- **Learning/testing**: Use your regular laptop with `--off-screen` and `--file`
|
||||
- **Small amounts**: Generate on a clean, updated machine with minimal software
|
||||
- **Testnet wallets**: Standard laptop is fine
|
||||
|
||||
Air-gapping is recommended for:
|
||||
|
||||
- **Life savings or business funds**
|
||||
- **Long-term cold storage** (multi-year hold)
|
||||
- **Institutional custody scenarios**
|
||||
|
||||
### Trust But Verify
|
||||
|
||||
The only way to fully trust this tool (or any wallet software) is to:
|
||||
|
||||
1. **Read the source code** (`src/pyhdwallet.py` is ~1400 lines, single file)
|
||||
2. **Verify test vectors** match published BIP39 test data
|
||||
3. **Run the test suite** on your air-gapped machine
|
||||
4. **Generate a test wallet** and verify addresses on a block explorer using a separate tool
|
||||
|
||||
Never trust wallet software blindly—especially for significant funds
|
||||
|
||||
---
|
||||
**Key additions:**
|
||||
|
||||
1. **Air-gapped setup procedure** with offline dependency installation
|
||||
2. **Threat model** (what air-gapping protects against and doesn't)
|
||||
3. **Physical security** best practices for mnemonic backup
|
||||
4. **Test suite as verification tool** before generating production keys
|
||||
5. **Entropy sources** explanation (dice rolls for paranoid users)
|
||||
6. **PGP fingerprint pinning** rationale
|
||||
7. **Operational security checklist** for production use
|
||||
8. **Risk-based guidance** (when air-gapping is overkill vs. essential)
|
||||
9. **"Trust but verify"** philosophy for crypto software
|
||||
Reference in New Issue
Block a user