From 4a73a7ecd460c034f0707a31081ca94abe24f776 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Mon, 3 Jan 2022 14:33:30 +0000 Subject: [PATCH] remove public header from all messages, fix envelope sizes (#251) * fix envelope sizes * only send sender DH pub key for per-queue E2E with confirmation message --- migrations/20210101_initial.sql | 2 - protocol/simplex-messaging.md | 33 +++++++------- src/Simplex/Messaging/Agent.hs | 48 ++++++++++----------- src/Simplex/Messaging/Agent/Client.hs | 16 +++---- src/Simplex/Messaging/Agent/Store.hs | 6 +-- src/Simplex/Messaging/Agent/Store/SQLite.hs | 34 ++++++--------- src/Simplex/Messaging/Crypto.hs | 1 + src/Simplex/Messaging/Encoding.hs | 9 ++++ src/Simplex/Messaging/Protocol.hs | 4 +- tests/AgentTests/SQLiteTests.hs | 13 ++---- 10 files changed, 80 insertions(+), 86 deletions(-) diff --git a/migrations/20210101_initial.sql b/migrations/20210101_initial.sql index 4cfa9ac95..595aa2b48 100644 --- a/migrations/20210101_initial.sql +++ b/migrations/20210101_initial.sql @@ -26,7 +26,6 @@ CREATE TABLE rcv_queues ( rcv_private_key BLOB NOT NULL, rcv_dh_secret BLOB NOT NULL, e2e_priv_key BLOB NOT NULL, - e2e_snd_pub_key BLOB, e2e_dh_secret BLOB, snd_id BLOB NOT NULL, snd_key BLOB, @@ -45,7 +44,6 @@ CREATE TABLE snd_queues ( snd_id BLOB NOT NULL, conn_alias BLOB NOT NULL REFERENCES connections ON DELETE CASCADE, snd_private_key BLOB NOT NULL, - e2e_pub_key BLOB NOT NULL, e2e_dh_secret BLOB NOT NULL, status TEXT NOT NULL, smp_server_version INTEGER NOT NULL DEFAULT 1, diff --git a/protocol/simplex-messaging.md b/protocol/simplex-messaging.md index 4f3153726..960b5e7a7 100644 --- a/protocol/simplex-messaging.md +++ b/protocol/simplex-messaging.md @@ -567,10 +567,11 @@ This command is sent to the server by the sender both to confirm the queue after ```abnf send = %s"SEND " smpEncMessage smpEncMessage = smpPubHeader sentMsgBody ; message up to 15968 bytes -smpPubHeader = smpClientVersion senderPublicDhKey +smpPubHeader = smpClientVersion (%x01 senderPublicDhKey / %x00) smpClientVersion = word16 senderPublicDhKey = length x509encoded ; sender's Curve25519 public key to agree DH secret for E2E encryption in this queue +; it is only sent in confirmation message x509encoded = sentMsgBody = 15842*15842 OCTET ; E2E-encrypted smpClientMessage padded to 15842 bytes before encryption @@ -609,21 +610,21 @@ SMP transmission structure for sent messages: ``` ------- transmission (= 16384 bytes) 2 | originalLength - 398- | signature SP sessionId SP corrId SP queueId SP %s"SEND" SP - ....... smpEncMessage (= 15968 bytes) + 396- | signature sessionId corrId queueId %s"SEND" SP (1+114 + 1+32? + 1+32 + 1+24 + 4+1 = 210) + ....... smpEncMessage (= 15968 bytes = 16384 - 416 bytes) 126- | smpPubHeader 24 | nonce for smpClientMessage - ------- smpClientMessage (E2E encrypted, = 15842 bytes) + ------- smpClientMessage (E2E encrypted, = 15802 bytes = 15968 - 166) 2 | originalLength 16- | smpPrivHeader ....... - | clientMsgBody (<= 15784 bytes) + | clientMsgBody (<= 15784 bytes = 15802 - 18) ....... 0+ | smpClientMessage pad ------- smpClientMessage end 16 | auth tag for smpClientMessage ....... smpEncMessage end - 16+ | transmission pad + 18+ | transmission pad ------- transmission end ``` @@ -632,28 +633,28 @@ SMP transmission structure for received messages: ``` ------- transmission (= 16384 bytes) 2 | originalLength - 398- | signature SP sessionId SP corrId SP queueId SP %s"MSG" SP msgId SP timestamp SP - ------- serverEncryptedMsg (= 15986 bytes) + 396- | signature sessionId corrId queueId %s"MSG" SP msgId timestamp (1+114 + 1+32? + 1+32 + 1+24 + 3+1 + 24+1 + 8 = 243) + ------- serverEncryptedMsg (= 15970 bytes = 16384 - 414 bytes) 2 | originalLength - ....... smpEncMessage (= 15968 bytes) + ....... smpEncMessage (= 15968 bytes = 15970 - 2 bytes) 126- | smpPubHeader 24 | nonce for smpClientMessage - ------- smpClientMessage (E2E encrypted, = 15842 bytes) + ------- smpClientMessage (E2E encrypted, = 15802 bytes = 15968 - 166 bytes) 2 | originalLength 16- | smpPrivHeader - ....... clientMsgBody (<= 15784 bytes) + ....... clientMsgBody (<= 15784 bytes = 15802 - 18) -- TODO move internal structure to agent protocol - 16- | agentPublicHeader - ....... E2E double-ratchet encrypted (= 15768) + 16- | agentPublicHeader (the size is for user messages post handshake, without E2E X3DH keys) + ....... E2E double-ratchet encrypted (= 15768 bytes = 15784 - 16) 96 | double-ratchet header 16 | double-ratchet header auth tag 24 | double-ratchet header iv - ------- encrypted agent message (= 15616 bytes) + ------- encrypted agent message (= 15616 bytes = 15768 - 152) 2 | originalLength 122 (90) | agentHeader 4 | %s"MSG" SP ....... - | application message (<= 15488 bytes) + | application message (<= 15488 bytes = 15616 - 128) ....... 0+ | encrypted agent message pad ------- encrypted agent message end @@ -665,9 +666,9 @@ SMP transmission structure for received messages: ------- smpClientMessage end 16 | auth tag for smpClientMessage ....... smpEncMessage end - 16 | auth tag (msgId is used as nonce) 0+ | serverEncryptedMsg pad ------- serverEncryptedMsg end + 16 | auth tag (msgId is used as nonce) 0+ | transmission pad ------- transmission end ``` diff --git a/src/Simplex/Messaging/Agent.hs b/src/Simplex/Messaging/Agent.hs index 486efe247..e38c4c3ee 100644 --- a/src/Simplex/Messaging/Agent.hs +++ b/src/Simplex/Messaging/Agent.hs @@ -332,7 +332,7 @@ rejectContact' _ contactConnId invId = processConfirmation :: AgentMonad m => AgentClient -> RcvQueue -> SMPConfirmation -> m () processConfirmation c rq@RcvQueue {e2ePrivKey} SMPConfirmation {senderKey, e2ePubKey} = do let dhSecret = C.dh' e2ePubKey e2ePrivKey - withStore $ \st -> setRcvQueueConfirmedE2E st rq e2ePubKey dhSecret + withStore $ \st -> setRcvQueueConfirmedE2E st rq dhSecret secureQueue c rq senderKey withStore $ \st -> setRcvQueueStatus st rq Secured @@ -522,39 +522,38 @@ processSMPTransmission c@AgentClient {subQ} (srv, rId, cmd) = do _ -> atomically $ writeTBQueue subQ ("", "", ERR $ CONN NOT_FOUND) where processSMP :: SConnType c -> ConnData -> RcvQueue -> m () - processSMP cType ConnData {connId} rq@RcvQueue {rcvDhSecret, e2ePrivKey, e2eShared, status} = + processSMP cType ConnData {connId} rq@RcvQueue {rcvDhSecret, e2ePrivKey, e2eDhSecret, status} = case cmd of SMP.MSG srvMsgId srvTs msgBody' -> handleNotifyAck $ do -- TODO deduplicate with previously received msgBody <- agentCbDecrypt rcvDhSecret (C.cbNonce srvMsgId) msgBody' - encMessage@SMP.EncMessage {emHeader = SMP.PubHeader v e2ePubKey} <- + encMessage@SMP.EncMessage {emHeader = SMP.PubHeader v e2ePubKey_} <- liftEither $ parse smpP (AGENT A_MESSAGE) msgBody - case e2eShared of - Nothing -> do - let e2eDhSecret = C.dh' e2ePubKey e2ePrivKey + case (e2eDhSecret, e2ePubKey_) of + (Nothing, Just e2ePubKey) -> do + let e2eDh = C.dh' e2ePubKey e2ePrivKey (_, agentMessage) <- - decryptAgentMessage e2eDhSecret encMessage + decryptAgentMessage e2eDh encMessage case agentMessage of AgentConfirmation senderKey connInfo -> do smpConfirmation SMPConfirmation {senderKey, e2ePubKey, connInfo} ack AgentInvitation cReq cInfo -> smpInvitation cReq cInfo >> ack _ -> prohibited >> ack - Just (e2eSndPubKey, e2eDhSecret) - | e2eSndPubKey /= e2ePubKey -> prohibited >> ack - | otherwise -> do - (msg, agentMessage) <- - decryptAgentMessage e2eDhSecret encMessage - case agentMessage of - AgentMessage AHeader {sndMsgId, prevMsgHash} aMsg -> case aMsg of - HELLO -> helloMsg >> ack - REPLY cReq -> replyMsg cReq >> ack - A_MSG body -> do - -- note that there is no ACK sent here, it is sent with agent's user ACK command - -- TODO add hash to other messages - let msgHash = C.sha256Hash msg - agentClientMsg prevMsgHash sndMsgId (srvMsgId, systemToUTCTime srvTs) body msgHash - _ -> prohibited >> ack + (Just e2eDh, Nothing) -> do + (msg, agentMessage) <- + decryptAgentMessage e2eDh encMessage + case agentMessage of + AgentMessage AHeader {sndMsgId, prevMsgHash} aMsg -> case aMsg of + HELLO -> helloMsg >> ack + REPLY cReq -> replyMsg cReq >> ack + A_MSG body -> do + -- note that there is no ACK sent here, it is sent with agent's user ACK command + -- TODO add hash to other messages + let msgHash = C.sha256Hash msg + agentClientMsg prevMsgHash sndMsgId (srvMsgId, systemToUTCTime srvTs) body msgHash + _ -> prohibited >> ack + _ -> prohibited >> ack SMP.END -> do removeSubscription c connId logServer "<--" c srv rId "END" @@ -576,8 +575,8 @@ processSMPTransmission c@AgentClient {subQ} (srv, rId, cmd) = do ack = sendAck c rq decryptAgentMessage :: C.DhSecretX25519 -> SMP.EncMessage -> m (ByteString, AgentMessage) - decryptAgentMessage e2eDhSecret SMP.EncMessage {emNonce, emBody} = do - msg <- agentCbDecrypt e2eDhSecret emNonce emBody + decryptAgentMessage e2eDh SMP.EncMessage {emNonce, emBody} = do + msg <- agentCbDecrypt e2eDh emNonce emBody agentMessage <- liftEither $ clientToAgentMsg =<< parse smpP (AGENT A_MESSAGE) msg pure (msg, agentMessage) @@ -699,7 +698,6 @@ newSndQueue_ a (SMPQueueUri smpServer senderId clientVersion rcvE2ePubDhKey) cIn { server = smpServer, sndId = senderId, sndPrivateKey, - e2ePubKey, e2eDhSecret = C.dh' rcvE2ePubDhKey e2ePrivKey, status = New } diff --git a/src/Simplex/Messaging/Agent/Client.hs b/src/Simplex/Messaging/Agent/Client.hs index 8d6d82346..e5e1a2ca7 100644 --- a/src/Simplex/Messaging/Agent/Client.hs +++ b/src/Simplex/Messaging/Agent/Client.hs @@ -251,7 +251,7 @@ newRcvQueue_ a c srv = do rcvPrivateKey, rcvDhSecret = C.dh' rcvPublicDhKey privDhKey, e2ePrivKey, - e2eShared = Nothing, + e2eDhSecret = Nothing, sndId = Just sndId, status = New } @@ -305,14 +305,14 @@ logSecret :: ByteString -> ByteString logSecret bs = encode $ B.take 3 bs sendConfirmation :: forall m. AgentMonad m => AgentClient -> SndQueue -> SMPConfirmation -> m () -sendConfirmation c sq@SndQueue {server, sndId} SMPConfirmation {senderKey, connInfo} = +sendConfirmation c sq@SndQueue {server, sndId} SMPConfirmation {senderKey, e2ePubKey, connInfo} = withLogSMP_ c server sndId "SEND " $ \smp -> do msg <- mkConfirmation liftSMP $ sendSMPMessage smp Nothing sndId msg where mkConfirmation :: m MsgBody mkConfirmation = - agentCbEncrypt sq . serializeAgentMessage $ + agentCbEncrypt sq (Just e2ePubKey) . serializeAgentMessage $ AgentConfirmation senderKey connInfo sendHello :: forall m. AgentMonad m => AgentClient -> SndQueue -> RetryInterval -> m () @@ -326,7 +326,7 @@ sendHello c sq@SndQueue {server, sndId, sndPrivateKey} ri = where mkHello :: m ByteString mkHello = do - agentCbEncrypt sq . serializeAgentMessage $ + agentCbEncrypt sq Nothing . serializeAgentMessage $ AgentMessage (AHeader 0 "") HELLO sendInvitation :: forall m. AgentMonad m => AgentClient -> SMPQueueUri -> ConnectionRequest 'CMInvitation -> ConnInfo -> m () @@ -363,11 +363,11 @@ deleteQueue c RcvQueue {server, rcvId, rcvPrivateKey} = sendAgentMessage :: AgentMonad m => AgentClient -> SndQueue -> ByteString -> m () sendAgentMessage c sq@SndQueue {server, sndId, sndPrivateKey} msg = withLogSMP_ c server sndId "SEND " $ \smp -> do - msg' <- agentCbEncrypt sq msg + msg' <- agentCbEncrypt sq Nothing msg liftSMP $ sendSMPMessage smp (Just sndPrivateKey) sndId msg' -agentCbEncrypt :: AgentMonad m => SndQueue -> ByteString -> m ByteString -agentCbEncrypt SndQueue {e2ePubKey, e2eDhSecret} msg = do +agentCbEncrypt :: AgentMonad m => SndQueue -> Maybe C.PublicKeyX25519 -> ByteString -> m ByteString +agentCbEncrypt SndQueue {e2eDhSecret} e2ePubKey msg = do emNonce <- liftIO C.randomCbNonce emBody <- liftEither . first cryptoError $ @@ -385,7 +385,7 @@ agentCbEncryptOnce dhRcvPubKey msg = do liftEither . first cryptoError $ C.cbEncrypt e2eDhSecret emNonce msg SMP.e2eEncMessageLength -- TODO per-queue client version - let emHeader = SMP.PubHeader (maxVersion SMP.smpClientVersion) dhSndPubKey + let emHeader = SMP.PubHeader (maxVersion SMP.smpClientVersion) (Just dhSndPubKey) pure $ smpEncode SMP.EncMessage {emHeader, emNonce, emBody} agentCbDecrypt :: AgentMonad m => C.DhSecretX25519 -> C.CbNonce -> ByteString -> m ByteString diff --git a/src/Simplex/Messaging/Agent/Store.hs b/src/Simplex/Messaging/Agent/Store.hs index 05a31c16a..97a25ea3a 100644 --- a/src/Simplex/Messaging/Agent/Store.hs +++ b/src/Simplex/Messaging/Agent/Store.hs @@ -44,7 +44,7 @@ class Monad m => MonadAgentStore s m where upgradeRcvConnToDuplex :: s -> ConnId -> SndQueue -> m () upgradeSndConnToDuplex :: s -> ConnId -> RcvQueue -> m () setRcvQueueStatus :: s -> RcvQueue -> QueueStatus -> m () - setRcvQueueConfirmedE2E :: s -> RcvQueue -> C.PublicKeyX25519 -> C.DhSecretX25519 -> m () + setRcvQueueConfirmedE2E :: s -> RcvQueue -> C.DhSecretX25519 -> m () setSndQueueStatus :: s -> SndQueue -> QueueStatus -> m () -- Confirmations @@ -85,7 +85,7 @@ data RcvQueue = RcvQueue -- | private DH key related to public sent to sender out-of-band (to agree simple per-queue e2e) e2ePrivKey :: C.PrivateKeyX25519, -- | public sender's DH key and agreed shared DH secret for simple per-queue e2e - e2eShared :: Maybe (C.PublicKeyX25519, C.DhSecretX25519), + e2eDhSecret :: Maybe C.DhSecretX25519, -- | sender queue ID sndId :: Maybe SMP.SenderId, -- | queue status @@ -100,8 +100,6 @@ data SndQueue = SndQueue sndId :: SMP.SenderId, -- | key used by the sender to sign transmissions sndPrivateKey :: SndPrivateSignKey, - -- | public DH key that was (or needs to be) sent to the recipient in SMP confirmation (to agree simple per-queue e2e) - e2ePubKey :: C.PublicKeyX25519, -- | shared DH secret agreed for simple per-queue e2e encryption e2eDhSecret :: C.DhSecretX25519, -- | queue status diff --git a/src/Simplex/Messaging/Agent/Store/SQLite.hs b/src/Simplex/Messaging/Agent/Store/SQLite.hs index b31cc247e..aba154090 100644 --- a/src/Simplex/Messaging/Agent/Store/SQLite.hs +++ b/src/Simplex/Messaging/Agent/Store/SQLite.hs @@ -241,20 +241,18 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto |] [":status" := status, ":host" := host, ":port" := port, ":rcv_id" := rcvId] - setRcvQueueConfirmedE2E :: SQLiteStore -> RcvQueue -> C.PublicKeyX25519 -> C.DhSecretX25519 -> m () - setRcvQueueConfirmedE2E st RcvQueue {rcvId, server = SMPServer {host, port}} e2eSndPubKey e2eDhSecret = + setRcvQueueConfirmedE2E :: SQLiteStore -> RcvQueue -> C.DhSecretX25519 -> m () + setRcvQueueConfirmedE2E st RcvQueue {rcvId, server = SMPServer {host, port}} e2eDhSecret = liftIO . withTransaction st $ \db -> DB.executeNamed db [sql| UPDATE rcv_queues - SET e2e_snd_pub_key = :e2e_snd_pub_key, - e2e_dh_secret = :e2e_dh_secret, + SET e2e_dh_secret = :e2e_dh_secret, status = :status WHERE host = :host AND port = :port AND rcv_id = :rcv_id |] [ ":status" := Confirmed, - ":e2e_snd_pub_key" := e2eSndPubKey, ":e2e_dh_secret" := e2eDhSecret, ":host" := host, ":port" := port, @@ -621,15 +619,13 @@ upsertServer_ dbConn SMPServer {host, port, keyHash} = do insertRcvQueue_ :: DB.Connection -> ConnId -> RcvQueue -> IO () insertRcvQueue_ dbConn connId RcvQueue {..} = do - let e2eSndPubKey = fst <$> e2eShared :: Maybe C.PublicKeyX25519 - e2eDhSecret = snd <$> e2eShared :: Maybe C.DhSecretX25519 DB.executeNamed dbConn [sql| INSERT INTO rcv_queues - ( host, port, rcv_id, conn_alias, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_snd_pub_key, e2e_dh_secret, snd_id, status) + ( host, port, rcv_id, conn_alias, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_dh_secret, snd_id, status) VALUES - (:host,:port,:rcv_id,:conn_alias,:rcv_private_key,:rcv_dh_secret,:e2e_priv_key,:e2e_snd_pub_key,:e2e_dh_secret,:snd_id,:status); + (:host,:port,:rcv_id,:conn_alias,:rcv_private_key,:rcv_dh_secret,:e2e_priv_key,:e2e_dh_secret,:snd_id,:status); |] [ ":host" := host server, ":port" := port server, @@ -638,7 +634,6 @@ insertRcvQueue_ dbConn connId RcvQueue {..} = do ":rcv_private_key" := rcvPrivateKey, ":rcv_dh_secret" := rcvDhSecret, ":e2e_priv_key" := e2ePrivKey, - ":e2e_snd_pub_key" := e2eSndPubKey, ":e2e_dh_secret" := e2eDhSecret, ":snd_id" := sndId, ":status" := status @@ -652,16 +647,15 @@ insertSndQueue_ dbConn connId SndQueue {..} = do dbConn [sql| INSERT INTO snd_queues - ( host, port, snd_id, conn_alias, snd_private_key, e2e_pub_key, e2e_dh_secret, status) + ( host, port, snd_id, conn_alias, snd_private_key, e2e_dh_secret, status) VALUES - (:host,:port,:snd_id,:conn_alias,:snd_private_key,:e2e_pub_key,:e2e_dh_secret,:status); + (:host,:port,:snd_id,:conn_alias,:snd_private_key,:e2e_dh_secret,:status); |] [ ":host" := host server, ":port" := port server, ":snd_id" := sndId, ":conn_alias" := connId, ":snd_private_key" := sndPrivateKey, - ":e2e_pub_key" := e2ePubKey, ":e2e_dh_secret" := e2eDhSecret, ":status" := status ] @@ -697,17 +691,16 @@ getRcvQueueByConnAlias_ dbConn connId = dbConn [sql| SELECT s.key_hash, q.host, q.port, q.rcv_id, q.rcv_private_key, q.rcv_dh_secret, - q.e2e_priv_key, q.e2e_snd_pub_key, q.e2e_dh_secret, q.snd_id, q.status + q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.status FROM rcv_queues q INNER JOIN servers s ON q.host = s.host AND q.port = s.port WHERE q.conn_alias = ?; |] (Only connId) where - rcvQueue [(keyHash, host, port, rcvId, rcvPrivateKey, rcvDhSecret, e2ePrivKey, e2eSndPubKey, e2eDhSecret, sndId, status)] = + rcvQueue [(keyHash, host, port, rcvId, rcvPrivateKey, rcvDhSecret, e2ePrivKey, e2eDhSecret, sndId, status)] = let server = SMPServer host port keyHash - e2eShared = (,) <$> e2eSndPubKey <*> e2eDhSecret - in Just RcvQueue {server, rcvId, rcvPrivateKey, rcvDhSecret, e2ePrivKey, e2eShared, sndId, status} + in Just RcvQueue {server, rcvId, rcvPrivateKey, rcvDhSecret, e2ePrivKey, e2eDhSecret, sndId, status} rcvQueue _ = Nothing getSndQueueByConnAlias_ :: DB.Connection -> ConnId -> IO (Maybe SndQueue) @@ -716,17 +709,16 @@ getSndQueueByConnAlias_ dbConn connId = <$> DB.query dbConn [sql| - SELECT s.key_hash, q.host, q.port, q.snd_id, q.snd_private_key, - q.e2e_pub_key, q.e2e_dh_secret, q.status + SELECT s.key_hash, q.host, q.port, q.snd_id, q.snd_private_key, q.e2e_dh_secret, q.status FROM snd_queues q INNER JOIN servers s ON q.host = s.host AND q.port = s.port WHERE q.conn_alias = ?; |] (Only connId) where - sndQueue [(keyHash, host, port, sndId, sndPrivateKey, e2ePubKey, e2eDhSecret, status)] = + sndQueue [(keyHash, host, port, sndId, sndPrivateKey, e2eDhSecret, status)] = let server = SMPServer host port keyHash - in Just SndQueue {server, sndId, sndPrivateKey, e2ePubKey, e2eDhSecret, status} + in Just SndQueue {server, sndId, sndPrivateKey, e2eDhSecret, status} sndQueue _ = Nothing -- * updateRcvIds helpers diff --git a/src/Simplex/Messaging/Crypto.hs b/src/Simplex/Messaging/Crypto.hs index 9231fba09..17ba5776e 100644 --- a/src/Simplex/Messaging/Crypto.hs +++ b/src/Simplex/Messaging/Crypto.hs @@ -815,6 +815,7 @@ cbDecrypt secret (CbNonce nonce) packet tag = Poly1305.auth rs c newtype CbNonce = CbNonce {unCbNonce :: ByteString} + deriving (Show) cbNonce :: ByteString -> CbNonce cbNonce s diff --git a/src/Simplex/Messaging/Encoding.hs b/src/Simplex/Messaging/Encoding.hs index b1164145e..dad328fba 100644 --- a/src/Simplex/Messaging/Encoding.hs +++ b/src/Simplex/Messaging/Encoding.hs @@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} @@ -66,6 +67,14 @@ instance Encoding ByteString where smpEncode s = B.cons (w2c len) s where len = fromIntegral $ B.length s smpP = A.take . fromIntegral . c2w =<< A.anyChar +instance Encoding a => Encoding (Maybe a) where + smpEncode s = maybe "\0" (("\1" <>) . smpEncode) s + smpP = + smpP >>= \case + '\0' -> pure Nothing + '\1' -> Just <$> smpP + _ -> fail "invalid Maybe tag" + newtype Tail = Tail {unTail :: ByteString} instance Encoding Tail where diff --git a/src/Simplex/Messaging/Protocol.hs b/src/Simplex/Messaging/Protocol.hs index bb76f226d..27c766c98 100644 --- a/src/Simplex/Messaging/Protocol.hs +++ b/src/Simplex/Messaging/Protocol.hs @@ -322,11 +322,13 @@ data EncMessage = EncMessage emNonce :: C.CbNonce, emBody :: ByteString } + deriving (Show) data PubHeader = PubHeader { phVersion :: Word16, - phE2ePubDhKey :: C.PublicKeyX25519 + phE2ePubDhKey :: Maybe C.PublicKeyX25519 } + deriving (Show) instance Encoding PubHeader where smpEncode (PubHeader v k) = smpEncode (v, k) diff --git a/tests/AgentTests/SQLiteTests.hs b/tests/AgentTests/SQLiteTests.hs index 63d361de9..752dd944b 100644 --- a/tests/AgentTests/SQLiteTests.hs +++ b/tests/AgentTests/SQLiteTests.hs @@ -137,9 +137,9 @@ testForeignKeysEnabled = let inconsistentQuery = [sql| INSERT INTO snd_queues - ( host, port, snd_id, conn_alias, snd_private_key, e2e_pub_key, e2e_dh_secret, status) + ( host, port, snd_id, conn_alias, snd_private_key, e2e_dh_secret, status) VALUES - ('smp.simplex.im', '5223', '1234', '2345', x'', x'', x'', 'new'); + ('smp.simplex.im', '5223', '1234', '2345', x'', x'', 'new'); |] DB.execute_ db inconsistentQuery `shouldThrow` (\e -> DB.sqlError e == DB.ErrorConstraint) @@ -150,9 +150,6 @@ cData1 = ConnData {connId = "conn1"} testPrivateSignKey :: C.APrivateSignKey testPrivateSignKey = C.APrivateSignKey C.SEd25519 "MC4CAQAwBQYDK2VwBCIEIDfEfevydXXfKajz3sRkcQ7RPvfWUPoq6pu1TYHV1DEe" -testPubDhKey :: C.PublicKeyX25519 -testPubDhKey = "MCowBQYDK2VuAyEAjiswwI3O/NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o=" - testPrivDhKey :: C.PrivateKeyX25519 testPrivDhKey = "MC4CAQAwBQYDK2VuBCIEINCzbVFaCiYHoYncxNY8tSIfn0pXcIAhLBfFc0m+gOpk" @@ -167,7 +164,7 @@ rcvQueue1 = rcvPrivateKey = testPrivateSignKey, rcvDhSecret = testDhSecret, e2ePrivKey = testPrivDhKey, - e2eShared = Nothing, + e2eDhSecret = Nothing, sndId = Just "2345", status = New } @@ -178,7 +175,6 @@ sndQueue1 = { server = SMPServer "smp.simplex.im" (Just "5223") testKeyHash, sndId = "3456", sndPrivateKey = testPrivateSignKey, - e2ePubKey = testPubDhKey, e2eDhSecret = testDhSecret, status = New } @@ -309,7 +305,6 @@ testUpgradeRcvConnToDuplex = { server = SMPServer "smp.simplex.im" (Just "5223") testKeyHash, sndId = "2345", sndPrivateKey = testPrivateSignKey, - e2ePubKey = testPubDhKey, e2eDhSecret = testDhSecret, status = New } @@ -331,7 +326,7 @@ testUpgradeSndConnToDuplex = rcvPrivateKey = testPrivateSignKey, rcvDhSecret = testDhSecret, e2ePrivKey = testPrivDhKey, - e2eShared = Nothing, + e2eDhSecret = Nothing, sndId = Just "4567", status = New }