This commit is contained in:
Evgeny @ SimpleX Chat
2026-06-28 21:47:26 +00:00
parent 26755c3688
commit 1d18ca9dce
3 changed files with 12 additions and 41 deletions
+11 -34
View File
@@ -4779,24 +4779,14 @@ signChannelNameProof GroupInfo {groupKeys, membership = GroupMember {memberId =
access {simplexName = Just $ SimplexNameClaim name (Just $ signNameProof memberPrivKey (Just mid) name (PHSimplexLink (ACSL SCMContact groupLink)))}
_ -> access
-- | The outcome of verifying a name claim: verified, a determinate failure (persist Just False), or
-- inconclusive (can't verify — leave the stored status untouched). The Text is a human-readable reason
-- for the UI; name-verification failures are rare, so the reason is a string rather than a typed enum
-- the clients would have to switch on.
data NameVerifyOutcome = NVOVerified | NVOFailed Text | NVOInconclusive Text
-- §4.6: a name verifies when the proof's presHeader is the link the peer was actually connected through
-- (so the proof can't be reused on a different link) AND the proof is signed by the key the name resolves to (the address root key, or the
-- channel owner's key selected by linkOwnerId). The key comes from *resolving the name* (the address),
-- not the connected link — for a 1-time invite they differ. A network/agent error propagates as
-- ChatErrorAgent so a UI-triggered verify can retry, rather than recording a false verdict.
verifyName :: User -> NetworkRequestMode -> SimplexNameInfo -> Maybe AConnShortLink -> Maybe NameClaimProof -> CM NameVerifyOutcome
-- returns (verdict to persist, reason for the UI); Nothing verdict = inconclusive, leave the stored status
verifyName :: User -> NetworkRequestMode -> SimplexNameInfo -> Maybe AConnShortLink -> Maybe NameClaimProof -> CM (Maybe Bool, Maybe Text)
verifyName user nm claim connLink_ proof_ = case (proof_, connLink_) of
(Nothing, _) -> pure $ NVOInconclusive "no name proof to verify"
(_, Nothing) -> pure $ NVOInconclusive "no connection link to check the name proof against"
(Nothing, _) -> pure (Nothing, Just "no name proof to verify")
(_, Nothing) -> pure (Nothing, Just "no connection link to check the name proof against")
(Just proof, Just connLink)
| not (proofBoundTo proof connLink) ->
pure $ NVOFailed "the name proof is bound to a different link than the one used to connect"
pure (Just False, Just "the name proof is bound to a different link than the one used to connect")
| otherwise -> do
let SimplexNameInfo {nameType, nameDomain} = claim
NameRecord {nrSimplexContact, nrSimplexChannel} <-
@@ -4805,13 +4795,13 @@ verifyName user nm claim connLink_ proof_ = case (proof_, connLink_) of
NTContact -> nrSimplexContact
NTPublicGroup -> nrSimplexChannel
if null resolvedLinks
then pure $ NVOFailed "the name is not registered (it does not resolve to any address)"
then pure (Just False, Just "the name is not registered (it does not resolve to any address)")
else do
ok <- or <$> mapM (verifyProofKey nm user claim proof) resolvedLinks
pure $
if ok
then NVOVerified
else NVOFailed "the name resolves to a different address — its owner did not sign this name proof"
then (Just True, Nothing)
else (Just False, Just "the name resolves to a different address — its owner did not sign this name proof")
proofBoundTo :: NameClaimProof -> AConnShortLink -> Bool
proofBoundTo NameClaimProof {presHeader} connLink =
@@ -4840,25 +4830,12 @@ verifyNameClaim ni claimedName_ = do
unless (claimedName_ == Just ni) $ throwChatError $ CESimplexName ni SNEUnknownName
pure (Just True)
nameVerifyVerdict :: NameVerifyOutcome -> Maybe Bool
nameVerifyVerdict = \case
NVOVerified -> Just True
NVOFailed _ -> Just False
NVOInconclusive _ -> Nothing
nameVerifyReason :: NameVerifyOutcome -> Maybe Text
nameVerifyReason = \case
NVOVerified -> Nothing
NVOFailed r -> Just r
NVOInconclusive r -> Just r
-- claim-check, verify the proof, persist the verdict; returns the human-readable failure reason for the UI
verifyEntityName :: User -> NetworkRequestMode -> Maybe SimplexNameInfo -> Maybe AConnShortLink -> Maybe NameClaimProof -> String -> (Bool -> CM ()) -> CM (Maybe Text)
verifyEntityName user nm claim_ connLink_ proof_ noNameErr persist = do
claim <- maybe (throwCmdError noNameErr) pure claim_
outcome <- verifyName user nm claim connLink_ proof_
forM_ (nameVerifyVerdict outcome) persist
pure $ nameVerifyReason outcome
(verdict, reason) <- verifyName user nm claim connLink_ proof_
forM_ verdict persist
pure reason
data ConnectViaContactResult
= CVRConnectedContact Contact
+1 -1
View File
@@ -54,7 +54,7 @@ import Data.Time (addUTCTime)
import Data.Time.Calendar (fromGregorian)
import Data.Time.Clock (UTCTime (..), diffUTCTime, getCurrentTime, nominalDiffTimeToSeconds, secondsToDiffTime)
import Simplex.Chat.Badges (BadgeCredential (..), ProofPresHeader (..), BadgeProof (..), BadgeStatus (..), LocalBadge (..), badgeProof, mkBadgeStatus, verifyBadge)
import Simplex.Chat.Names (SimplexNameClaim (..), claimName, mkSimplexNameClaim, signNameProof)
import Simplex.Chat.Names (SimplexNameClaim (..), claimName, mkSimplexNameClaim)
import Simplex.Chat.Call
import Simplex.Chat.Controller
import Simplex.Chat.Files
-6
View File
@@ -50,7 +50,6 @@ module Simplex.Chat.Store.Profiles
getUserAddressConnection,
deleteUserAddress,
getUserAddress,
getUserAddressSigKey,
setUserSimplexName,
getUserContactLinkById,
getGroupLinkInfo,
@@ -524,11 +523,6 @@ getUserAddress db User {userId} =
ExceptT . firstRow toUserContactLink SEUserContactLinkNotFound $
DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND local_display_name = '' AND group_id IS NULL") (Only userId)
getUserAddressSigKey :: DB.Connection -> User -> IO (Maybe C.PrivateKeyEd25519)
getUserAddressSigKey db User {userId} =
fmap join . maybeFirstRow fromOnly $
DB.query db "SELECT link_priv_sig_key FROM user_contact_links WHERE user_id = ? AND local_display_name = '' AND group_id IS NULL" (Only userId)
getUserContactLinkById :: DB.Connection -> UserId -> Int64 -> ExceptT StoreError IO (UserContactLink, Maybe GroupLinkInfo)
getUserContactLinkById db userId userContactLinkId =
ExceptT . firstRow (\(ucl :. gli) -> (toUserContactLink ucl, toGroupLinkInfo gli)) SEUserContactLinkNotFound $