From 2ceb09b0efb5f79a6135551455484a31063d8f2e Mon Sep 17 00:00:00 2001 From: shum Date: Tue, 29 Sep 2026 13:10:06 +0000 Subject: [PATCH] core: compress signed conn info with PQ --- src/Simplex/Chat/Library/Commands.hs | 2 +- src/Simplex/Chat/Library/Internal.hs | 29 ++++++++++++++------------ src/Simplex/Chat/Library/Subscriber.hs | 2 +- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index 15e3716112..4fe288ca8e 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -3981,7 +3981,7 @@ processChatCommand cxt nm = \case dm <- case gInfo_ of Just (Just gInfo@(GIK g gks)) | useRelays' g -> case relayMemberId_ of - Just relayMemberId -> encodeXMemberConnInfo gInfo relayMemberId profileToSend + Just relayMemberId -> encodeXMemberConnInfo pqSup gInfo relayMemberId profileToSend Nothing -> throwChatError $ CEInternalError "relay group join without target relay memberId" | otherwise -> encodeConnInfoPQ pqSup $ XContact profileToSend (Just $ groupMemberKey gks) (Just xContactId) welcomeSharedMsgId msg_ _ -> diff --git a/src/Simplex/Chat/Library/Internal.hs b/src/Simplex/Chat/Library/Internal.hs index be03d1277b..0d048a937b 100644 --- a/src/Simplex/Chat/Library/Internal.hs +++ b/src/Simplex/Chat/Library/Internal.hs @@ -2446,32 +2446,35 @@ encodeConnInfoPQ pqSup chatMsgEvent = do cxt <- chatStoreCxt let info = ChatMessage {chatVRange = vr cxt, msgId = Nothing, chatMsgEvent} case encodeChatMessage maxEncodedInfoLength info of - ECMEncoded connInfo -> case pqSup of - PQSupportOn | B.length connInfo > maxCompressedInfoLength -> do - let connInfo' = compressedBatchMsgBody_ connInfo - when (B.length connInfo' > maxCompressedInfoLength) $ throwChatError $ CEException "large compressed info" - pure connInfo' - _ -> pure connInfo + ECMEncoded connInfo -> compressConnInfoPQ pqSup connInfo ECMLarge -> throwChatError $ CEException "large info" -- conn-info wrapped as a signed element, so the receiver can verify the signature over the body -encodeSignedConnInfo :: MsgEncodingI e => MsgSigning -> ChatMsgEvent e -> CM ByteString -encodeSignedConnInfo signing chatMsgEvent = do +encodeSignedConnInfo :: MsgEncodingI e => PQSupport -> MsgSigning -> ChatMsgEvent e -> CM ByteString +encodeSignedConnInfo pqSup signing chatMsgEvent = do vr <- chatVersionRange let info = ChatMessage {chatVRange = vr, msgId = Nothing, chatMsgEvent} case encodeChatMessage maxEncodedInfoLength info of - ECMEncoded body -> pure $ encodeBatchElement (Just $ signChatMsgBody signing body) body + ECMEncoded body -> compressConnInfoPQ pqSup $ encodeBatchElement (Just $ signChatMsgBody signing body) body ECMLarge -> throwChatError $ CEException "large signed info" +compressConnInfoPQ :: PQSupport -> ByteString -> CM ByteString +compressConnInfoPQ pqSup connInfo = case pqSup of + PQSupportOn | B.length connInfo > maxCompressedInfoLength -> do + let connInfo' = compressedBatchMsgBody_ connInfo + when (B.length connInfo' > maxCompressedInfoLength) $ throwChatError $ CEException "large compressed info" + pure connInfo' + _ -> pure connInfo + -- signed XMember for a relay-group join: proves the joiner holds the member key it asserts, and carries -- viaRelay = the target relay's memberId inside the signed body so a sibling relay can't accept a replay -encodeXMemberConnInfo :: GroupInfoKeys -> MemberId -> Profile -> CM ByteString -encodeXMemberConnInfo (GIK gInfo@GroupInfo {membership = GroupMember {memberId}} gks) relayMemberId profileToSend = +encodeXMemberConnInfo :: PQSupport -> GroupInfoKeys -> MemberId -> Profile -> CM ByteString +encodeXMemberConnInfo pqSup (GIK gInfo@GroupInfo {membership = GroupMember {memberId}} gks) relayMemberId profileToSend = let memberPrivKey' = memberPrivKey gks xMemberEvt = XMember profileToSend memberId (MemberKey $ C.publicKey memberPrivKey') (Just relayMemberId) bindingData = groupBindingData gInfo memberId (C.publicKey memberPrivKey') signing = MsgSigning CBGroup bindingData KRMember memberPrivKey' - in encodeSignedConnInfo signing xMemberEvt + in encodeSignedConnInfo pqSup signing xMemberEvt deliverMessage :: Connection -> CMEventTag e -> MsgBody -> MessageId -> CM (Int64, PQEncryption) deliverMessage conn cmEventTag msgBody msgId = do @@ -3045,7 +3048,7 @@ allowAgentConnectionAsync user conn@Connection {pqSupport} confId gInfo_ msg = d Just gInfo@(GIK g _) | useRelays' g || maxVersion (peerChatVRange conn) >= relayWebCapVersion -> groupMsgSigning False gInfo msg _ -> Nothing dm <- case signing_ of - Just signing -> encodeSignedConnInfo signing msg + Just signing -> encodeSignedConnInfo pqSupport signing msg Nothing -> encodeConnInfoPQ pqSupport msg allowAgentConnectionInfo user conn confId dm diff --git a/src/Simplex/Chat/Library/Subscriber.hs b/src/Simplex/Chat/Library/Subscriber.hs index 1dbf1adcb9..f956c292bc 100644 --- a/src/Simplex/Chat/Library/Subscriber.hs +++ b/src/Simplex/Chat/Library/Subscriber.hs @@ -1247,7 +1247,7 @@ processAgentMessageConn cxt user@User {userId} entity gks_ corrId agentConnId ag withStore' $ \db -> updateConnLinkData db user conn cReq cReqHash groupLinkId chatV pqSup let incognitoProfile = fromLocalProfile <$> incognitoMembershipProfile gInfo profileToSend <- presentUserBadge user incognitoProfile $ userProfileInGroup user gInfo incognitoProfile - dm <- encodeXMemberConnInfo g relayMemberId profileToSend + dm <- encodeXMemberConnInfo pqSup g relayMemberId profileToSend subMode <- chatReadVar subscriptionMode (cmdId, connId') <- prepareAgentJoin user (Just conn) True cReq joinAgentConnectionAsync cmdId True connId' True cReq dm subMode