mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-21 21:10:15 +00:00
move names
This commit is contained in:
@@ -40,6 +40,7 @@ library
|
||||
Simplex.Chat.AppSettings
|
||||
Simplex.Chat.Badges
|
||||
Simplex.Chat.Badges.CLI
|
||||
Simplex.Chat.Names
|
||||
Simplex.Chat.Call
|
||||
Simplex.Chat.Controller
|
||||
Simplex.Chat.Delivery
|
||||
|
||||
@@ -30,9 +30,6 @@ module Simplex.Chat.Badges
|
||||
maxFileSizeLegend,
|
||||
ProofPresHeaderTag (..),
|
||||
ProofPresHeader (..),
|
||||
NameClaimProof (..),
|
||||
signNameProof,
|
||||
verifyNameProofSig,
|
||||
proofPresHeaderLink,
|
||||
BadgePurchase (..),
|
||||
BadgeMasterKey (..),
|
||||
@@ -246,35 +243,6 @@ proofPresHeaderAccepted = \case
|
||||
PHSimplexLink _ -> True
|
||||
PHUnknown _ _ -> True
|
||||
|
||||
-- A name claim proof: signed by the address owner's key (linkOwnerId = Just oid when a channel
|
||||
-- owner other than the address signs, Nothing when the address's own root key signs) over
|
||||
-- strEncode name <> strEncode presHeader, tied to the link it is shown through.
|
||||
data NameClaimProof = NameClaimProof
|
||||
{ linkOwnerId :: Maybe (StrJSON "OwnerId" OwnerId),
|
||||
presHeader :: ProofPresHeader,
|
||||
signature :: C.Signature 'C.Ed25519
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
nameProofPayload :: SimplexNameInfo -> ProofPresHeader -> ByteString
|
||||
nameProofPayload name presHeader = strEncode name <> strEncode presHeader
|
||||
|
||||
-- linkOwnerId names the signing owner in the link's owner chain (Nothing = root key for a contact address).
|
||||
signNameProof :: C.PrivateKeyEd25519 -> Maybe OwnerId -> SimplexNameInfo -> ProofPresHeader -> NameClaimProof
|
||||
signNameProof key linkOwnerId name presHeader =
|
||||
NameClaimProof
|
||||
{ linkOwnerId = StrJSON <$> linkOwnerId,
|
||||
presHeader,
|
||||
signature = C.sign' key (nameProofPayload name presHeader)
|
||||
}
|
||||
|
||||
-- verify a name proof's signature against the resolved address owner key. The caller must
|
||||
-- SEPARATELY check the proof's presHeader link is the one it was shown through, so a proof made
|
||||
-- for one link can't be reused on another.
|
||||
verifyNameProofSig :: C.PublicKeyEd25519 -> SimplexNameInfo -> NameClaimProof -> Bool
|
||||
verifyNameProofSig ownerKey name NameClaimProof {presHeader, signature} =
|
||||
C.verify' ownerKey signature (nameProofPayload name presHeader)
|
||||
|
||||
proofPresHeaderLink :: ProofPresHeader -> Maybe AConnShortLink
|
||||
proofPresHeaderLink = \case
|
||||
PHSimplexLink lnk -> Just lnk
|
||||
@@ -444,13 +412,6 @@ $(JQ.deriveJSON defaultJSON ''BadgeCredential)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''BadgeProof)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''NameClaimProof)
|
||||
|
||||
-- NameClaimProof is stored as JSON in contact_profiles.contact_domain_proof (like a badge proof)
|
||||
instance ToField NameClaimProof where toField = toField . encodeJSON
|
||||
|
||||
instance FromField NameClaimProof where fromField = fromTextField_ decodeJSON
|
||||
|
||||
-- LocalBadge is sent to the UI/clients WITHOUT crypto - only disclosed info + status. The credential/proof
|
||||
-- bytes stay core-side. FromJSON reconstructs a display-only badge (empty proof) for read-only consumers
|
||||
-- (remote host, UI echoes); the authoritative badge is loaded from the DB (rowToBadge), never from this JSON.
|
||||
|
||||
@@ -55,7 +55,8 @@ import Data.Type.Equality
|
||||
import qualified Data.UUID as UUID
|
||||
import qualified Data.UUID.V4 as V4
|
||||
import Simplex.Chat.Library.Subscriber
|
||||
import Simplex.Chat.Badges (BadgeCredential (..), NameClaimProof (..), LocalBadge (..), ProofPresHeader (..), maxXFTPFileSize, mkBadgeStatus, proofPresHeaderLink, signNameProof, verifyCredential, verifyNameProofSig)
|
||||
import Simplex.Chat.Badges (BadgeCredential (..), LocalBadge (..), ProofPresHeader (..), maxXFTPFileSize, mkBadgeStatus, proofPresHeaderLink, verifyCredential)
|
||||
import Simplex.Chat.Names (NameClaimProof (..), signNameProof, verifyNameProofSig)
|
||||
import Simplex.Chat.Call
|
||||
import Simplex.Chat.Controller
|
||||
import Simplex.Chat.Delivery (DeliveryJobScope (..), DeliveryJobSpec (..), DeliveryWorkerScope (..))
|
||||
|
||||
@@ -53,7 +53,8 @@ import Data.Text.Encoding (encodeUtf8)
|
||||
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, signNameProof, verifyBadge)
|
||||
import Simplex.Chat.Badges (BadgeCredential (..), ProofPresHeader (..), BadgeProof (..), BadgeStatus (..), LocalBadge (..), badgeProof, mkBadgeStatus, verifyBadge)
|
||||
import Simplex.Chat.Names (signNameProof)
|
||||
import Simplex.Chat.Call
|
||||
import Simplex.Chat.Controller
|
||||
import Simplex.Chat.Files
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE KindSignatures #-}
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
module Simplex.Chat.Names
|
||||
( NameClaimProof (..),
|
||||
signNameProof,
|
||||
verifyNameProofSig,
|
||||
)
|
||||
where
|
||||
|
||||
import qualified Data.Aeson.TH as JQ
|
||||
import Data.ByteString.Char8 (ByteString)
|
||||
import Simplex.Chat.Badges (ProofPresHeader)
|
||||
import Simplex.Messaging.Agent.Protocol (OwnerId)
|
||||
import Simplex.Messaging.Agent.Store.DB (fromTextField_)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (defaultJSON)
|
||||
import Simplex.Messaging.SimplexName (SimplexNameInfo)
|
||||
import Simplex.Messaging.Util (decodeJSON, encodeJSON)
|
||||
#if defined(dbPostgres)
|
||||
import Database.PostgreSQL.Simple.FromField (FromField (..))
|
||||
import Database.PostgreSQL.Simple.ToField (ToField (..))
|
||||
#else
|
||||
import Database.SQLite.Simple.FromField (FromField (..))
|
||||
import Database.SQLite.Simple.ToField (ToField (..))
|
||||
#endif
|
||||
|
||||
-- A name claim proof: signed by the address owner's key (linkOwnerId = Just oid when a channel
|
||||
-- owner other than the address signs, Nothing when the address's own root key signs) over
|
||||
-- strEncode name <> strEncode presHeader, tied to the link it is shown through.
|
||||
data NameClaimProof = NameClaimProof
|
||||
{ linkOwnerId :: Maybe (StrJSON "OwnerId" OwnerId),
|
||||
presHeader :: ProofPresHeader,
|
||||
signature :: C.Signature 'C.Ed25519
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
nameProofPayload :: SimplexNameInfo -> ProofPresHeader -> ByteString
|
||||
nameProofPayload name presHeader = strEncode name <> strEncode presHeader
|
||||
|
||||
-- linkOwnerId names the signing owner in the link's owner chain (Nothing = root key for a contact address).
|
||||
signNameProof :: C.PrivateKeyEd25519 -> Maybe OwnerId -> SimplexNameInfo -> ProofPresHeader -> NameClaimProof
|
||||
signNameProof key linkOwnerId name presHeader =
|
||||
NameClaimProof
|
||||
{ linkOwnerId = StrJSON <$> linkOwnerId,
|
||||
presHeader,
|
||||
signature = C.sign' key (nameProofPayload name presHeader)
|
||||
}
|
||||
|
||||
-- verify a name proof's signature against the resolved address owner key. The caller must
|
||||
-- SEPARATELY check the proof's presHeader link is the one it was shown through, so a proof made
|
||||
-- for one link can't be reused on another.
|
||||
verifyNameProofSig :: C.PublicKeyEd25519 -> SimplexNameInfo -> NameClaimProof -> Bool
|
||||
verifyNameProofSig ownerKey name NameClaimProof {presHeader, signature} =
|
||||
C.verify' ownerKey signature (nameProofPayload name presHeader)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''NameClaimProof)
|
||||
|
||||
-- stored as JSON in contact_profiles.contact_domain_proof
|
||||
instance ToField NameClaimProof where toField = toField . encodeJSON
|
||||
|
||||
instance FromField NameClaimProof where fromField = fromTextField_ decodeJSON
|
||||
@@ -222,7 +222,8 @@ import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Time.Clock (NominalDiffTime, UTCTime (..), addUTCTime, getCurrentTime)
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Simplex.Chat.Badges (BadgeRow, NameClaimProof, badgeToRow, verifyBadge_)
|
||||
import Simplex.Chat.Badges (BadgeRow, badgeToRow, verifyBadge_)
|
||||
import Simplex.Chat.Names (NameClaimProof)
|
||||
import Simplex.Chat.Messages
|
||||
import Simplex.Chat.Operators
|
||||
import Simplex.Chat.Protocol hiding (Binary)
|
||||
|
||||
@@ -33,7 +33,8 @@ import qualified Data.Text as T
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Data.Time.Clock (UTCTime (..), getCurrentTime)
|
||||
import Data.Type.Equality
|
||||
import Simplex.Chat.Badges (BadgeRow, NameClaimProof, badgeToRow, rowToBadge, verifyBadge_)
|
||||
import Simplex.Chat.Badges (BadgeRow, badgeToRow, rowToBadge, verifyBadge_)
|
||||
import Simplex.Chat.Names (NameClaimProof)
|
||||
import Simplex.Chat.Messages
|
||||
import Simplex.Chat.Remote.Types
|
||||
import Simplex.Chat.Types
|
||||
|
||||
@@ -48,7 +48,8 @@ import Data.Text.Encoding (encodeUtf8)
|
||||
import Data.Time.Clock (UTCTime)
|
||||
import Data.Typeable (Typeable)
|
||||
import Data.Word (Word16)
|
||||
import Simplex.Chat.Badges (BadgeInfo (..), BadgeProof (..), BadgeStatus (..), NameClaimProof (..), LocalBadge (..), localBadgeInfo, localBadgeStatus, mkBadgeStatus, verifyBadge)
|
||||
import Simplex.Chat.Badges (BadgeInfo (..), BadgeProof (..), BadgeStatus (..), LocalBadge (..), localBadgeInfo, localBadgeStatus, mkBadgeStatus, verifyBadge)
|
||||
import Simplex.Chat.Names (NameClaimProof (..))
|
||||
import Simplex.Messaging.Crypto.BBS (BBSPublicKey)
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.Shared
|
||||
|
||||
Reference in New Issue
Block a user