mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-28 02:38:44 +00:00
core: refuse an account index BIP-32 cannot harden, whichever way it arrives
The counter path checked it, the explicit one did not, and the parser is not the only caller: processChatCommand takes APIWalletBind from library callers too. hardened leaves an index at or above 2^31 alone, so account i and i + 2^31 are the same key while the duplicate check compares the stored integers, and two profiles could hold one account's names. The rfc now says what hiding a profile from /_wallet does and does not protect: the seed is one per device, so whoever unlocks any profile can derive every account. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX
This commit is contained in:
co-authored by
Claude Opus 5
parent
3ad17ca477
commit
472ee5ef10
@@ -88,20 +88,22 @@ bindAccountIndex db user@User {userId} sId = \case
|
||||
if acct >= 0x80000000
|
||||
then pure $ Left "no free account on this key"
|
||||
else Right () <$ bindUser db userId sId acct
|
||||
Just acct -> do
|
||||
taken <-
|
||||
maybeFirstRow fromOnly $
|
||||
DB.query
|
||||
db
|
||||
"SELECT 1 FROM users WHERE wallet_seed_id = ? AND wallet_account_index = ? AND user_id != ?"
|
||||
(sId, fromIntegral acct :: Int64, userId)
|
||||
case (taken :: Maybe Int64) of
|
||||
Just _ -> pure $ Left "another profile uses this account"
|
||||
Nothing -> do
|
||||
bindUser db userId sId (fromIntegral acct)
|
||||
-- the counter moves past it, so the next profile is not handed the same one
|
||||
setNextAccountIndex db sId (fromIntegral acct + 1)
|
||||
pure $ Right ()
|
||||
Just acct
|
||||
| acct >= 0x80000000 -> pure $ Left "account index too large"
|
||||
| otherwise -> do
|
||||
taken <-
|
||||
maybeFirstRow fromOnly $
|
||||
DB.query
|
||||
db
|
||||
"SELECT 1 FROM users WHERE wallet_seed_id = ? AND wallet_account_index = ? AND user_id != ?"
|
||||
(sId, fromIntegral acct :: Int64, userId)
|
||||
case (taken :: Maybe Int64) of
|
||||
Just _ -> pure $ Left "another profile uses this account"
|
||||
Nothing -> do
|
||||
bindUser db userId sId (fromIntegral acct)
|
||||
-- the counter moves past it, so the next profile is not handed the same one
|
||||
setNextAccountIndex db sId (fromIntegral acct + 1)
|
||||
pure $ Right ()
|
||||
|
||||
-- | So two profiles cannot be handed the same account.
|
||||
takeAccountIndex :: DB.Connection -> SeedId -> IO Int64
|
||||
|
||||
Reference in New Issue
Block a user