feat: encrypt private keys at rest using keystore#44
Conversation
Wallet create and import now encrypt private keys using the standard Ethereum keystore format (AES-128-CTR + scrypt), the same format used by MetaMask, Geth, and Foundry. Users are prompted for a password on key creation/import and when any command needs the key. The POLYMARKET_PASSWORD env var supports non-interactive use (CI/scripts). Use --no-password to opt into plaintext storage (not recommended). Adds wallet export subcommand to decrypt and display the key. Fixes Polymarket#18 Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
…xt path Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
Addressed both cursor findings in d491d80:
|
Summary
~/.config/polymarket/config.jsonwere stored as plaintext - any process running as the same user could read themwallet createandwallet importnow encrypt keys using the standard Ethereum keystore format (AES-128-CTR + scrypt), the same format used by MetaMask, Geth, and FoundryPOLYMARKET_PASSWORDenv var for CI/scripts)--no-passwordflag available for plaintext storage (not recommended)wallet exportsubcommand to decrypt and display the key for backupNew dependencies
rpassword- secure terminal password input (no echo)rand0.8 - RNG for keystore encryptionalloysigner-keystorefeature - standard keystore encrypt/decryptFixes #18
Supersedes #19 (pre-refactor, needs full rewrite after #13)
Test plan
cargo fmt --checkpassescargo clippy -- -D warningspassescargo testpasses (131 tests)polymarket wallet createprompts for password and stores encrypted keystorepolymarket wallet create --no-passwordstores plaintext (with warning)polymarket wallet import <key>prompts for passwordpolymarket wallet exportdecrypts and shows keyPOLYMARKET_PASSWORD=xxx polymarket wallet addressworks without interactive promptThis contribution was developed with AI assistance (Claude Code).
Note
High Risk
Changes wallet key storage and retrieval to support encrypted keystore files and password prompting, which is security-sensitive and affects all commands that need a private key. Misconfiguration or edge cases (missing keystore, password handling, filesystem moves) could block access to funds or break automation.
Overview
Private keys are no longer stored in plaintext by default:
wallet create/wallet importnow write an Ethereum keystore file under~/.config/polymarket/keystoreand mark the config with anencryptedflag, prompting for a password (or usingPOLYMARKET_PASSWORD).Adds
wallet exportto decrypt and print the private key for backup, and introduces--no-passwordon create/import to explicitly keep legacy plaintext storage (with warnings/cleanup of leftover keystore files). This also updates dependencies to enable Alloy keystore support and addsrpassword/rand, with the lockfile pulling in keystore/crypto crates.Written by Cursor Bugbot for commit d491d80. This will update automatically on new commits. Configure here.