Security & Credentials Guide
Guide to credential management, encryption, and security best practices
Overview
The bot implements comprehensive security measures to protect your API credentials:
- AES-256-GCM encryption for stored credentials
- PBKDF2 key derivation with 100,000 iterations
- Automatic secret redaction in logs
- Secure memory handling for sensitive data
Encryption Flow
flowchart TB
subgraph Encryption["Credential Encryption Flow"]
PASS[Your Passphrase] --> PBKDF2[PBKDF2<br/>100k iterations]
PBKDF2 --> KEY[Encryption Key]
CREDS[API Credentials] --> AES[AES-256-GCM]
KEY --> AES
SALT[Unique Salt] --> AES
AES --> FILE[credentials.encrypted.json]
SALT --> SALTFILE[.credentials.salt]
end
style PASS fill:#fff3e0
style KEY fill:#e3f2fd
style FILE fill:#c8e6c9
style SALTFILE fill:#c8e6c9
Credential Setup Flow
sequenceDiagram
participant User
participant CLI as Wealth CLI
participant Crypto as Crypto Module
participant File as Encrypted File
User->>CLI: wealth credentials add binance
CLI->>User: Prompt for API Key
User->>CLI: Enter API Key (hidden)
CLI->>User: Prompt for Secret Key
User->>CLI: Enter Secret Key (hidden)
CLI->>Crypto: Encrypt with passphrase
Crypto->>File: Store encrypted
CLI->>User: Credentials saved securely
Encrypted Credentials (Recommended)
How It Works
Your exchange API credentials are encrypted using:
- Your passphrase → converted to encryption key via PBKDF2
- AES-256-GCM → industry-standard authenticated encryption
- Unique salt → stored separately for additional security
┌─────────────────┐ ┌─────────────────┐
│ Your Passphrase │────►│ PBKDF2 (100k) │────► Encryption Key
└─────────────────┘ └─────────────────┘
│
┌─────────────────┐ ▼
│ API Credentials │────► AES-256-GCM ────► credentials.encrypted.json
└─────────────────┘
Setup
# 1. Create the encrypted credentials file
wealth credentials create
# 2. Add your exchange credentials (interactive mode - recommended)
# You'll be prompted for passphrase if CREDENTIALS_PASSPHRASE is not set
wealth credentials add binance
wealth credentials add bybit
wealth credentials add hyperliquid
wealth credentials add aster
# Alternative: Add credentials with CLI args (less secure - appears in shell history)
# wealth credentials add binance --api-key YOUR_API_KEY --secret-key YOUR_SECRET_KEY
# 3. Verify everything works
wealth credentials verify
Interactive Passphrase Prompt
When running wealth run or wealth dashboard, the bot will automatically prompt for your passphrase if:
credentials.encrypted.jsonexists (you've set up encrypted credentials)CREDENTIALS_PASSPHRASEenvironment variable is not set
$ wealth dashboard
🔐 Enter credentials passphrase: ********
This allows you to run the bot without storing the passphrase in environment variables or shell history.
Behavior on cancellation: If you press Ctrl+C or enter an empty passphrase, the bot will attempt to fall back to environment-based credentials (legacy mode). If neither method provides valid credentials, the bot will fail with an error.
For automation: Set the CREDENTIALS_PASSPHRASE environment variable to skip the interactive prompt:
export CREDENTIALS_PASSPHRASE="your-secure-passphrase-here"
wealth run # No prompt, uses env var
Security Note: Always prefer the interactive mode (without --api-key and --secret-key flags) as it prevents credentials from appearing in your shell history. The bot will prompt you securely for these values.
Files Created
| File | Purpose | Security |
|---|---|---|
credentials.encrypted.json | Encrypted credentials | AES-256-GCM encrypted |
.credentials.salt | Encryption salt | Required for decryption |
⚠️ Both files are required for decryption. Back them up securely!
Production Best Practices
File Permissions
# Set restrictive permissions
chmod 600 credentials.encrypted.json
chmod 600 .credentials.salt
# Verify
ls -la credentials.encrypted.json .credentials.salt
# Should show: -rw------- (owner read/write only)
Passphrase Management
DO NOT:
- ❌ Store passphrase in plain text files
- ❌ Commit passphrase to version control
- ❌ Share passphrase in chat/email
- ❌ Use weak passphrases (< 12 characters)
- ❌ Reuse passphrases across environments
DO:
- ✅ Use secrets management systems (AWS Secrets Manager, HashiCorp Vault)
- ✅ Use strong passphrases (12+ characters, mixed case, numbers, symbols)
- ✅ Rotate passphrases regularly
- ✅ Different passphrases for testnet/mainnet
- ✅ Audit access to encrypted files
Examples:
# AWS Secrets Manager
export CREDENTIALS_PASSPHRASE="$(aws secretsmanager get-secret-value \
--secret-id prod/wealth/passphrase \
--query SecretString \
--output text)"
# HashiCorp Vault
export CREDENTIALS_PASSPHRASE="$(vault kv get \
-field=passphrase \
secret/wealth/prod)"
# Kubernetes Secret
export CREDENTIALS_PASSPHRASE="$(kubectl get secret wealth-passphrase \
-o jsonpath='{.data.passphrase}' | base64 -d)"
Version Control
Add to .gitignore:
# Encrypted credentials
credentials.encrypted.json
.credentials.salt
# Environment files
.env
.env.local
.env.*.local
Backup Strategy
What to backup:
.credentials.salt- CRITICAL - Cannot decrypt without thiscredentials.encrypted.json- Encrypted credentials- Passphrase - Store separately in secrets manager
Backup procedure:
# Backup to secure storage
aws s3 cp .credentials.salt s3://secure-backups/wealth/$(date +%Y%m%d)/
aws s3 cp credentials.encrypted.json s3://secure-backups/wealth/$(date +%Y%m%d)/
Docker Deployment
See Deployment Guide - Docker for complete Docker setup including Docker Compose configuration.
Kubernetes Deployment
See Deployment Guide - Kubernetes for complete K8s manifests and secrets management.
Security Audit Checklist
Before Production Deployment:
- Credentials encrypted with strong passphrase (12+ chars)
-
Salt file exists and backed up (
.credentials.salt) - File permissions set to 600
- Encrypted files excluded from version control
- Passphrase stored securely (not in plaintext files)
- No hardcoded credentials
-
Verification test passed (
wealth credentials verify) - Backup strategy implemented
- Credential rotation procedure documented
Troubleshooting
"Failed to decrypt credentials" error:
- Check passphrase is correct
- Verify
.credentials.saltfile exists and hasn't been modified - Ensure
credentials.encrypted.jsonhasn't been corrupted
"Salt file not found" error:
- Verify
.credentials.saltfile exists in current directory - Check file permissions (should be readable)
- Restore from backup if missing
Secrets still appearing in logs:
- Verify using
Secret<String>wrapper types - Check custom Debug implementation is present
- Grep logs for credential patterns:
grep -i "api_key" logs/ - Should only show
[REDACTED]
See Also
- CLI Reference - Credential management commands
- Configuration Guide - Environment variables
- Deployment Guide - Production deployment