perf(tx-cache): skip Argon2id for unencrypted wallets
Opening the transaction-history cache always derived its encryption key with Argon2id, even for an unencrypted wallet. For those wallets the passphrase is just a value derivable from the database itself, so the ~50-100 ms Argon2id stall bought no additional secrecy and ran on the UI thread at open. - Unencrypted wallets now derive the cache key with a cheap, domain-separated BLAKE2b KDF over the wallet identity, keyed by the per-wallet salt. The secret is derivable from the DB, so this is security-equivalent for the unencrypted case and avoids the stall. - Passphrase-encrypted wallets are unchanged: they keep the Argon2id key derivation. The two paths use separate domain labels, so the fast-path key and the Argon2id key never collide for the same DB and salt; a cache written under one cannot be read under the other. Tests cover the fast-path round-trip and reopen, and assert that an Argon2id unlock of the same DB produces a different key and fails to read the fast-path snapshot. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,9 @@ public:
|
||||
|
||||
bool ensureOpen();
|
||||
bool unlockWithPassphrase(const std::string& walletIdentity, const std::string& passphrase);
|
||||
// Unlock an UNENCRYPTED wallet's cache without Argon2id: the "secret" is derivable from the DB, so a
|
||||
// cheap domain-separated BLAKE2b KDF is security-equivalent and avoids a ~50-100 ms UI-thread stall.
|
||||
bool unlockUnencrypted(const std::string& walletIdentity);
|
||||
void lockKey();
|
||||
bool hasKey() const;
|
||||
bool isUnlockedFor(const std::string& walletIdentity) const;
|
||||
@@ -89,6 +92,9 @@ private:
|
||||
bool exec(const char* sql);
|
||||
bool createSchema();
|
||||
std::vector<unsigned char> getOrCreateSalt(const std::string& walletHash);
|
||||
static bool deriveKeyFast(const std::string& walletHash,
|
||||
const std::vector<unsigned char>& salt,
|
||||
std::array<unsigned char, 32>& keyOut); // BLAKE2b, label-separated
|
||||
static bool deriveKey(const std::string& passphrase,
|
||||
const std::vector<unsigned char>& salt,
|
||||
std::array<unsigned char, 32>& keyOut);
|
||||
|
||||
Reference in New Issue
Block a user