feat(chat): passphrase-wrapped local key vault for sensitive conversations

Adds ChatSensitiveVault: a per-wallet random 32-byte key wrapped under a user
passphrase (Argon2id MODERATE KEK + XSalsa20-Poly1305) in an 89-byte local file.
This key encrypts the at-rest rows of "sensitive" conversations INDEPENDENTLY of
the seed-derived chat key, so those rows can't be read by someone who has the
seed but not this passphrase — and a wallet restored from the seed alone can't
read them at all. Losing the passphrase/file makes them unrecoverable by design.
create/unlock/changePassphrase/remove, atomic write + 0600, keyOut zeroed on any
failure. Unit-tested (round-trip, wrong-passphrase zeroing, rekey, no-clobber).

Phase B, step 2 (local vault key).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 17:31:30 -05:00
co-authored by Claude Opus 4.8
parent 669b8b7ca5
commit 84ca1a5cbe
4 changed files with 251 additions and 0 deletions
+3
View File
@@ -499,6 +499,7 @@ set(APP_SOURCES
src/chat/chat_service.cpp
src/chat/chat_database.cpp
src/chat/chat_outgoing.cpp
src/chat/chat_sensitive_vault.cpp
src/wallet/lite_owned_string.cpp
src/wallet/lite_rollout_policy.cpp
src/wallet/lite_client_bridge.cpp
@@ -669,6 +670,7 @@ set(APP_HEADERS
src/chat/chat_service.h
src/chat/chat_database.h
src/chat/chat_outgoing.h
src/chat/chat_sensitive_vault.h
src/config/version.h
src/data/wallet_state.h
src/data/transaction_history_cache.h
@@ -1224,6 +1226,7 @@ if(BUILD_TESTING)
src/chat/chat_service.cpp
src/chat/chat_database.cpp
src/chat/chat_outgoing.cpp
src/chat/chat_sensitive_vault.cpp
src/wallet/lite_owned_string.cpp
src/wallet/lite_rollout_policy.cpp
src/wallet/lite_client_bridge.cpp