core: add chat items to indicate decryption failures due to ratchets being out of sync (#2175)

* core: add chat items to indicate decryption failures due to ratchets being out of sync

* show ratchet errors in chat items, show all integrity errors

* show decryption errors, tests

* ios: chat items, remove item for duplicate messages

* android: decryption errors chat items

* eol
This commit is contained in:
Evgeny Poberezkin authored and GitHub committed 2023-04-16 11:35:45 +01:00
1 parent 13cf1cc004
commit aea526f69d
21 files changed
+480 -75

No files matched your search

+50
View File
@@ -17,9 +17,11 @@ import qualified Data.ByteString.Lazy.Char8 as LB
import Simplex.Chat.Call
import Simplex.Chat.Controller (ChatConfig (..))
import Simplex.Chat.Options (ChatOpts (..))
import Simplex.Chat.Store (agentStoreFile, chatStoreFile)
import Simplex.Chat.Types (authErrDisableCount, sameVerificationCode, verificationCode)
import qualified Simplex.Messaging.Crypto as C
import System.Directory (copyFile, doesDirectoryExist, doesFileExist)
import System.FilePath ((</>))
import Test.Hspec
chatDirectTests :: SpecWith FilePath
@@ -79,6 +81,8 @@ chatDirectTests = do
sameVerificationCode "123 456 789" "12345 6789" `shouldBe` True
it "mark contact verified" testMarkContactVerified
it "mark group member verified" testMarkGroupMemberVerified
describe "message errors" $ do
it "show message decryption error and update count" testMsgDecryptError
testAddContact :: HasCallStack => SpecWith FilePath
testAddContact = versionTestMatrix2 runTestAddContact
@@ -1763,3 +1767,49 @@ testMarkGroupMemberVerified =
alice <## "member ID: 2"
alice <## "receiving messages via: localhost"
alice <## "sending messages via: localhost"
testMsgDecryptError :: HasCallStack => FilePath -> IO ()
testMsgDecryptError tmp =
withNewTestChat tmp "alice" aliceProfile $ \alice -> do
withNewTestChat tmp "bob" bobProfile $ \bob -> do
connectUsers alice bob
alice #> "@bob hi"
bob <# "alice> hi"
bob #> "@alice hey"
alice <# "bob> hey"
copyDb "bob" "bob_old"
withTestChat tmp "bob" $ \bob -> do
bob <## "1 contacts connected (use /cs for the list)"
alice #> "@bob hello"
bob <# "alice> hello"
bob #> "@alice hello too"
alice <# "bob> hello too"
withTestChat tmp "bob_old" $ \bob -> do
bob <## "1 contacts connected (use /cs for the list)"
alice #> "@bob 1"
bob <# "alice> decryption error, possibly due to the device change (header)"
alice #> "@bob 2"
alice #> "@bob 3"
(bob </)
bob ##> "/tail @alice 1"
bob <# "alice> decryption error, possibly due to the device change (header, 3 messages)"
bob #> "@alice 1"
alice <# "bob> decryption error, possibly due to the device change (header)"
bob #> "@alice 2"
bob #> "@alice 3"
(alice </)
alice ##> "/tail @bob 1"
alice <# "bob> decryption error, possibly due to the device change (header, 3 messages)"
alice #> "@bob 4"
bob <# "alice> decryption error, possibly due to the device change (header)"
withTestChat tmp "bob" $ \bob -> do
bob <## "1 contacts connected (use /cs for the list)"
alice #> "@bob hello again"
bob <# "alice> skipped message ID 5..8"
bob <# "alice> hello again"
bob #> "@alice received!"
alice <# "bob> received!"
where
copyDb from to = do
copyFile (chatStoreFile $ tmp </> from) (chatStoreFile $ tmp </> to)
copyFile (agentStoreFile $ tmp </> from) (agentStoreFile $ tmp </> to)
+78
View File
@@ -9,7 +9,10 @@ import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (concurrently_)
import Control.Monad (when)
import qualified Data.Text as T
import Simplex.Chat.Store (agentStoreFile, chatStoreFile)
import Simplex.Chat.Types (GroupMemberRole (..))
import System.Directory (copyFile)
import System.FilePath ((</>))
import Test.Hspec
chatGroupTests :: SpecWith FilePath
@@ -48,6 +51,8 @@ chatGroupTests = do
it "leaving groups with unused host contacts deletes incognito profiles" testGroupLinkIncognitoUnusedHostContactsDeleted
it "group link member role" testGroupLinkMemberRole
it "leaving and deleting the group joined via link should NOT delete previously existing direct contacts" testGroupLinkLeaveDelete
describe "group message errors" $ do
it "show message decryption error and update count" testGroupMsgDecryptError
testGroup :: HasCallStack => SpecWith FilePath
testGroup = versionTestMatrix3 runTestGroup
@@ -1986,3 +1991,76 @@ testGroupLinkLeaveDelete =
bob ##> "/contacts"
bob <## "alice (Alice)"
bob <## "cath (Catherine)"
testGroupMsgDecryptError :: HasCallStack => FilePath -> IO ()
testGroupMsgDecryptError tmp =
withNewTestChat tmp "alice" aliceProfile $ \alice -> do
withNewTestChat tmp "cath" cathProfile $ \cath -> do
withNewTestChat tmp "bob" bobProfile $ \bob -> do
createGroup3 "team" alice bob cath
alice #> "#team hi"
[bob, cath] *<# "#team alice> hi"
bob #> "#team hey"
[alice, cath] *<# "#team bob> hey"
copyDb "bob" "bob_old"
withTestChat tmp "bob" $ \bob -> do
bob <## "2 contacts connected (use /cs for the list)"
bob <## "#team: connected to server(s)"
alice #> "#team hello"
[bob, cath] *<# "#team alice> hello"
bob #> "#team hello too"
[alice, cath] *<# "#team bob> hello too"
withTestChat tmp "bob_old" $ \bob -> do
bob <## "2 contacts connected (use /cs for the list)"
bob <## "#team: connected to server(s)"
alice #> "#team 1"
bob <# "#team alice> decryption error, possibly due to the device change (header)"
cath <# "#team alice> 1"
alice #> "#team 2"
cath <# "#team alice> 2"
alice #> "#team 3"
cath <# "#team alice> 3"
(bob </)
bob ##> "/tail #team 1"
bob <# "#team alice> decryption error, possibly due to the device change (header, 3 messages)"
bob #> "#team 1"
alice <# "#team bob> decryption error, possibly due to the device change (header)"
-- cath <# "#team bob> 1"
bob #> "#team 2"
cath <# "#team bob> incorrect message hash"
cath <# "#team bob> 2"
bob #> "#team 3"
cath <# "#team bob> 3"
(alice </)
alice ##> "/tail #team 1"
alice <# "#team bob> decryption error, possibly due to the device change (header, 3 messages)"
alice #> "#team 4"
(bob </)
cath <# "#team alice> 4"
bob ##> "/tail #team 4"
bob
<##? [ "#team alice> decryption error, possibly due to the device change (header, 4 messages)",
"#team 1",
"#team 2",
"#team 3"
]
withTestChat tmp "bob" $ \bob -> do
bob <## "2 contacts connected (use /cs for the list)"
bob <## "#team: connected to server(s)"
alice #> "#team hello again"
bob <# "#team alice> skipped message ID 8..11"
[bob, cath] *<# "#team alice> hello again"
bob #> "#team received!"
alice <# "#team bob> received!"
bob #> "#team 4"
alice <# "#team bob> 4"
bob #> "#team 5"
cath <# "#team bob> decryption error, possibly due to the device change (earlier message, 2 messages)"
cath <# "#team bob> incorrect message hash"
[alice, cath] *<# "#team bob> 5"
bob #> "#team 6"
[alice, cath] *<# "#team bob> 6"
where
copyDb from to = do
copyFile (chatStoreFile $ tmp </> from) (chatStoreFile $ tmp </> to)
copyFile (agentStoreFile $ tmp </> from) (agentStoreFile $ tmp </> to)
+3
View File
@@ -272,6 +272,9 @@ getInAnyOrder f cc ls = do
(<#) :: HasCallStack => TestCC -> String -> Expectation
cc <# line = (dropTime <$> getTermLine cc) `shouldReturn` line
(*<#) :: HasCallStack => [TestCC] -> String -> Expectation
ccs *<# line = concurrentlyN_ $ map (<# line) ccs
(?<#) :: HasCallStack => TestCC -> String -> Expectation
cc ?<# line = (dropTime <$> getTermLine cc) `shouldReturn` "i " <> line