@@ -33,6 +33,10 @@ import org.junit.runner.RunWith
33
33
import org.junit.runners.JUnit4
34
34
import org.junit.runners.MethodSorters
35
35
import org.matrix.android.sdk.InstrumentedTest
36
+ import org.matrix.android.sdk.api.auth.UIABaseAuth
37
+ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
38
+ import org.matrix.android.sdk.api.auth.UserPasswordAuth
39
+ import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
36
40
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
37
41
import org.matrix.android.sdk.api.session.Session
38
42
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
@@ -61,7 +65,10 @@ import org.matrix.android.sdk.common.CommonTestHelper
61
65
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runCryptoTest
62
66
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
63
67
import org.matrix.android.sdk.common.SessionTestParams
68
+ import org.matrix.android.sdk.common.TestConstants
64
69
import org.matrix.android.sdk.mustFail
70
+ import timber.log.Timber
71
+ import kotlin.coroutines.Continuation
65
72
import kotlin.coroutines.resume
66
73
67
74
// @Ignore("This test fails with an unhandled exception thrown from a coroutine which terminates the entire test run.")
@@ -607,6 +614,85 @@ class E2eeSanityTests : InstrumentedTest {
607
614
)
608
615
}
609
616
617
+ @Test
618
+ fun test_EncryptionDoesNotHinderVerification () = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
619
+ val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
620
+
621
+ val aliceSession = cryptoTestData.firstSession
622
+ val bobSession = cryptoTestData.secondSession
623
+
624
+ val aliceAuthParams = UserPasswordAuth (
625
+ user = aliceSession.myUserId,
626
+ password = TestConstants .PASSWORD
627
+ )
628
+ val bobAuthParams = UserPasswordAuth (
629
+ user = bobSession!! .myUserId,
630
+ password = TestConstants .PASSWORD
631
+ )
632
+
633
+ testHelper.waitForCallback {
634
+ aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor {
635
+ override fun performStage (flowResponse : RegistrationFlowResponse , errCode : String? , promise : Continuation <UIABaseAuth >) {
636
+ promise.resume(aliceAuthParams)
637
+ }
638
+ }, it)
639
+ }
640
+
641
+ testHelper.waitForCallback {
642
+ bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor {
643
+ override fun performStage (flowResponse : RegistrationFlowResponse , errCode : String? , promise : Continuation <UIABaseAuth >) {
644
+ promise.resume(bobAuthParams)
645
+ }
646
+ }, it)
647
+ }
648
+
649
+ // add a second session for bob but not cross signed
650
+
651
+ val secondBobSession = testHelper.logIntoAccount(bobSession.myUserId, SessionTestParams (true ))
652
+
653
+ aliceSession.cryptoService().setGlobalBlacklistUnverifiedDevices(true )
654
+
655
+ // The two bob session should not be able to decrypt any message
656
+
657
+ val roomFromAlicePOV = aliceSession.getRoom(cryptoTestData.roomId)!!
658
+ Timber .v(" #TEST: Send a first message that should be withheld" )
659
+ val sentEvent = sendMessageInRoom(testHelper, roomFromAlicePOV, " Hello" )!!
660
+
661
+ // wait for it to be synced back the other side
662
+ Timber .v(" #TEST: Wait for message to be synced back" )
663
+ testHelper.retryPeriodically {
664
+ bobSession.roomService().getRoom(cryptoTestData.roomId)?.timelineService()?.getTimelineEvent(sentEvent) != null
665
+ }
666
+
667
+ testHelper.retryPeriodically {
668
+ secondBobSession.roomService().getRoom(cryptoTestData.roomId)?.timelineService()?.getTimelineEvent(sentEvent) != null
669
+ }
670
+
671
+ // bob should not be able to decrypt
672
+ Timber .v(" #TEST: Ensure cannot be decrytped" )
673
+ cryptoTestHelper.ensureCannotDecrypt(listOf (sentEvent), bobSession, cryptoTestData.roomId)
674
+ cryptoTestHelper.ensureCannotDecrypt(listOf (sentEvent), secondBobSession, cryptoTestData.roomId)
675
+
676
+ // let's try to verify, it should work even if bob devices are untrusted
677
+ Timber .v(" #TEST: Do the verification" )
678
+ cryptoTestHelper.verifySASCrossSign(aliceSession, bobSession, cryptoTestData.roomId)
679
+
680
+ Timber .v(" #TEST: Send a second message, outbound session should have rotated and only bob 1rst session should decrypt" )
681
+
682
+ val secondEvent = sendMessageInRoom(testHelper, roomFromAlicePOV, " World" )!!
683
+ Timber .v(" #TEST: Wait for message to be synced back" )
684
+ testHelper.retryPeriodically {
685
+ bobSession.roomService().getRoom(cryptoTestData.roomId)?.timelineService()?.getTimelineEvent(secondEvent) != null
686
+ }
687
+
688
+ testHelper.retryPeriodically {
689
+ secondBobSession.roomService().getRoom(cryptoTestData.roomId)?.timelineService()?.getTimelineEvent(secondEvent) != null
690
+ }
691
+
692
+ cryptoTestHelper.ensureCanDecrypt(listOf (secondEvent), bobSession, cryptoTestData.roomId, listOf (" World" ))
693
+ cryptoTestHelper.ensureCannotDecrypt(listOf (secondEvent), secondBobSession, cryptoTestData.roomId)
694
+ }
695
+
610
696
private suspend fun VerificationService.readOldVerificationCodeAsync (scope : CoroutineScope , userId : String ): Deferred <String > {
611
697
return scope.async {
612
698
suspendCancellableCoroutine { continuation ->
0 commit comments