-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
Signing Service: Two-Tier Local Key Management (Encrypted Keyfile + Secure Enclave)
Owner: Yash
Priority: P0 — blocks onchain permit signing
Crate: signer/
Depends on: Credential Vault (#XX), Policy Engine (#XX)
Blocked by: None
Summary
Implement a two-tier signing service for secp256k1 private keys used in EIP-712 permit signing. Users can either import an existing key or generate a fresh wallet during setup. Both paths encrypt immediately — no plaintext ever touches disk.
| Tier | Mode | Protection | Availability |
|---|---|---|---|
| Tier 1 | encrypted-keyfile | Argon2id-derived key + libsodium secretbox | All platforms |
| Tier 2 | secure-enclave | Tier 1 + encryption key sealed to macOS Secure Enclave hardware | macOS with Apple Silicon / T2 |
There is no fishnet signer export command. The full private key is never retrievable after initial generation or import. If the user loses their master password and SE access, the key is gone. This is by design — same as hardware wallets. Recovery path is:
- Use the original key from wherever they sourced it (their wallet backup, or the backup they made during
generate) fishnet signer importorfishnet signer generatefor a new key- Call
setSigner()on smart wallets if address changed
Acceptance Criteria
-
fishnet initoffers choice: import existing key OR generate new wallet - Import path: accepts pasted private key, encrypts immediately, no plaintext on disk
- Generate path: creates secp256k1 keypair, displays full key once, requires backup confirmation before encrypting
- Tier 1 (encrypted-keyfile) works on Linux and macOS
- Tier 2 (secure-enclave) auto-detects and activates on supported macOS hardware
-
fishnet signer statusshows mode, public address, blurred key, SE binding, last used -
fishnet signer revealshows blurred key after master password auth, clears terminal after keypress -
fishnet signer importreplaces existing key, logs event in audit log, warns about onchain impact -
fishnet signer generatecreates new keypair, shows full key once, encrypts after confirmation -
fishnet signer rotatealiases to import with replace semantics -
fishnet signer pubkeyoutputs address for contract deployment - Blurred key format:
0x+ first 4 hex +••••••••••+ last 4 hex — consistent everywhere - Blurred key cached in DB at creation time (no decryption needed to display)
- Dashboard signer card shows status, address, blurred key behind [reveal], mode badge, color indicator
- Dashboard settings page supports import, generate, reveal, SE upgrade, and diagnostics
- Generate flow in dashboard: two-step (generate → confirm), pending key discarded if modal closed
- All API endpoints except pubkey enforce master password authentication
-
/api/signer/generateis the only endpoint that ever returns a full private key - Signing path: decrypt → mlock → sign → zeroize, key in memory < 100ms
- Argon2id params: 256MB memory cost, 3 iterations
-
fishnet doctorvalidates signer health and SE binding - Unit tests: encrypt/decrypt roundtrip, zeroize verification, generate keypair, blur formatting, SE mock for CI
- Integration test: init → generate key → sign permit → verify signature matches public address
- Integration test: init → import key → sign permit → verify signature matches public address
Reactions are currently unavailable