fix(wallet-switch): cluster A — identity/secret teardown on wallet switch
From the wallet-switching audit (HIGH-severity cross-wallet leaks): - Chat identity leak: the full-node switch (switchToWallet) and seed-migration adopt reset state_ but NOT the HushChat identity, so wallet A's decrypted conversations surfaced under wallet B and outgoing chat was signed with A's keypair. Factor the existing teardown into App::resetChatSession() and call it on both wallet-change paths (the lite path already reset it via rebuildLiteWallet, which now uses the helper too). - Global PIN vault: the PIN quick-unlock vault was a single vault.dat, so after a switch wallet A's stored passphrase was offered/applied to encrypted wallet B. SecureVault is now scoped per wallet (vault-<walletfile>.dat); the default wallet keeps the legacy vault.dat for back-compat. vault_ is constructed for the active wallet and re-scoped on switch, so B has its own (empty) vault. - Lock-screen state: switching now clears the carried-over failed-attempt counter + lockout timer and secure-zeroes the passphrase/PIN entry buffers so the previous wallet's unlock state can't apply to the new one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+11
-3
@@ -29,9 +29,15 @@ namespace util {
|
||||
*/
|
||||
class SecureVault {
|
||||
public:
|
||||
SecureVault();
|
||||
// `walletFile` scopes the vault to a specific wallet.dat so one wallet's PIN passphrase is never
|
||||
// offered for another. The default wallet ("wallet.dat" / empty) keeps the legacy global vault.dat
|
||||
// path for backward compatibility; other wallets get their own vault-<scope>.dat.
|
||||
explicit SecureVault(const std::string& walletFile = "");
|
||||
~SecureVault();
|
||||
|
||||
// Re-scope to a different wallet (called when the active wallet changes).
|
||||
void setWalletScope(const std::string& walletFile);
|
||||
|
||||
/**
|
||||
* @brief Check if a vault file exists on disk
|
||||
*/
|
||||
@@ -78,15 +84,17 @@ public:
|
||||
static void secureZero(void* ptr, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get the vault file path
|
||||
* @brief Get this vault's file path (scoped to its wallet)
|
||||
*/
|
||||
static std::string getVaultPath();
|
||||
std::string getVaultPath() const;
|
||||
|
||||
private:
|
||||
// Derive a 32-byte key from PIN + salt using Argon2id
|
||||
bool deriveKey(const std::string& pin,
|
||||
const uint8_t* salt, size_t saltLen,
|
||||
uint8_t* key, size_t keyLen) const;
|
||||
|
||||
std::string scope_; // "" = default/legacy wallet (vault.dat); else a sanitized wallet-file tag
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
Reference in New Issue
Block a user