Do some cleanup on verification APIs

This commit is contained in:
ganfra 2022-04-25 17:55:37 +02:00
parent 309a290cb8
commit 8bd094fa66
19 changed files with 323 additions and 514 deletions

View File

@ -30,8 +30,7 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
@ -311,16 +310,16 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
} }
// we should reach SHOW SAS on both // we should reach SHOW SAS on both
var alicePovTx: OutgoingSasVerificationTransaction? = null var alicePovTx: SasVerificationTransaction? = null
var bobPovTx: IncomingSasVerificationTransaction? = null var bobPovTx: SasVerificationTransaction? = null
// wait for alice to get the ready // wait for alice to get the ready
testHelper.waitWithLatch { testHelper.waitWithLatch {
testHelper.retryPeriodicallyWithLatch(it) { testHelper.retryPeriodicallyWithLatch(it) {
bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID) as? IncomingSasVerificationTransaction bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID) as? SasVerificationTransaction
Log.v("TEST", "== bobPovTx is ${alicePovTx?.uxState}") Log.v("TEST", "== bobPovTx is ${bobPovTx?.state}")
if (bobPovTx?.state == VerificationTxState.OnStarted) { if (bobPovTx?.state == VerificationTxState.OnStarted) {
bobPovTx?.performAccept() bobPovTx?.acceptVerification()
true true
} else { } else {
false false
@ -330,18 +329,18 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
testHelper.waitWithLatch { testHelper.waitWithLatch {
testHelper.retryPeriodicallyWithLatch(it) { testHelper.retryPeriodicallyWithLatch(it) {
alicePovTx = aliceVerificationService.getExistingTransaction(bob.myUserId, requestID) as? OutgoingSasVerificationTransaction alicePovTx = aliceVerificationService.getExistingTransaction(bob.myUserId, requestID) as? SasVerificationTransaction
Log.v("TEST", "== alicePovTx is ${alicePovTx?.uxState}") Log.v("TEST", "== alicePovTx is ${alicePovTx?.state}")
alicePovTx?.state == VerificationTxState.ShortCodeReady alicePovTx?.state == VerificationTxState.ShortCodeReady
} }
} }
// wait for alice to get the ready // wait for alice to get the ready
testHelper.waitWithLatch { testHelper.waitWithLatch {
testHelper.retryPeriodicallyWithLatch(it) { testHelper.retryPeriodicallyWithLatch(it) {
bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID) as? IncomingSasVerificationTransaction bobPovTx = bobVerificationService.getExistingTransaction(alice.myUserId, requestID) as? SasVerificationTransaction
Log.v("TEST", "== bobPovTx is ${alicePovTx?.uxState}") Log.v("TEST", "== bobPovTx is ${bobPovTx?.state}")
if (bobPovTx?.state == VerificationTxState.OnStarted) { if (bobPovTx?.state == VerificationTxState.OnStarted) {
bobPovTx?.performAccept() bobPovTx?.acceptVerification()
} }
bobPovTx?.state == VerificationTxState.ShortCodeReady bobPovTx?.state == VerificationTxState.ShortCodeReady
} }

View File

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.crosssigning
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest import androidx.test.filters.LargeTest
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
@ -53,7 +54,7 @@ class XSigningTest : InstrumentedTest {
fun test_InitializeAndStoreKeys() { fun test_InitializeAndStoreKeys() {
val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true)) val aliceSession = testHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
testHelper.doSync<Unit> { testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService() aliceSession.cryptoService().crossSigningService()
.initializeCrossSigning(object : UserInteractiveAuthInterceptor { .initializeCrossSigning(object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
@ -65,10 +66,12 @@ class XSigningTest : InstrumentedTest {
) )
) )
} }
}, it) })
} }
val myCrossSigningKeys = aliceSession.cryptoService().crossSigningService().getMyCrossSigningKeys() val myCrossSigningKeys = testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().getMyCrossSigningKeys()
}
val masterPubKey = myCrossSigningKeys?.masterKey() val masterPubKey = myCrossSigningKeys?.masterKey()
assertNotNull("Master key should be stored", masterPubKey?.unpaddedBase64PublicKey) assertNotNull("Master key should be stored", masterPubKey?.unpaddedBase64PublicKey)
val selfSigningKey = myCrossSigningKeys?.selfSigningKey() val selfSigningKey = myCrossSigningKeys?.selfSigningKey()
@ -78,7 +81,10 @@ class XSigningTest : InstrumentedTest {
assertTrue("Signing Keys should be trusted", myCrossSigningKeys?.isTrusted() == true) assertTrue("Signing Keys should be trusted", myCrossSigningKeys?.isTrusted() == true)
assertTrue("Signing Keys should be trusted", aliceSession.cryptoService().crossSigningService().checkUserTrust(aliceSession.myUserId).isVerified()) val userTrustResult = testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().checkUserTrust(aliceSession.myUserId)
}
assertTrue("Signing Keys should be trusted", userTrustResult.isVerified())
testHelper.signOutAndClose(aliceSession) testHelper.signOutAndClose(aliceSession)
} }
@ -99,29 +105,37 @@ class XSigningTest : InstrumentedTest {
password = TestConstants.PASSWORD password = TestConstants.PASSWORD
) )
testHelper.doSync<Unit> { testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
promise.resume(aliceAuthParams) promise.resume(aliceAuthParams)
} }
}, it) })
} }
testHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { testHelper.runBlockingTest {
bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
promise.resume(bobAuthParams) promise.resume(bobAuthParams)
} }
}, it) } })
}
// Check that alice can see bob keys // Check that alice can see bob keys
testHelper.runBlockingTest { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true) } testHelper.runBlockingTest { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true) }
val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobSession.myUserId) val bobKeysFromAlicePOV = testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobSession.myUserId)
}
assertNotNull("Alice can see bob Master key", bobKeysFromAlicePOV!!.masterKey()) assertNotNull("Alice can see bob Master key", bobKeysFromAlicePOV!!.masterKey())
assertNull("Alice should not see bob User key", bobKeysFromAlicePOV.userKey()) assertNull("Alice should not see bob User key", bobKeysFromAlicePOV.userKey())
assertNotNull("Alice can see bob SelfSigned key", bobKeysFromAlicePOV.selfSigningKey()) assertNotNull("Alice can see bob SelfSigned key", bobKeysFromAlicePOV.selfSigningKey())
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.masterKey()?.unpaddedBase64PublicKey, bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey) val myKeys = testHelper.runBlockingTest {
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.selfSigningKey()?.unpaddedBase64PublicKey, bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.selfSigningKey()?.unpaddedBase64PublicKey) bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()
}
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.masterKey()?.unpaddedBase64PublicKey, myKeys?.masterKey()?.unpaddedBase64PublicKey)
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.selfSigningKey()?.unpaddedBase64PublicKey, myKeys?.selfSigningKey()?.unpaddedBase64PublicKey)
assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted()) assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
@ -145,25 +159,33 @@ class XSigningTest : InstrumentedTest {
password = TestConstants.PASSWORD password = TestConstants.PASSWORD
) )
testHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
promise.resume(aliceAuthParams) promise.resume(aliceAuthParams)
} }
}, it) } })
testHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor { }
testHelper.runBlockingTest {
bobSession.cryptoService().crossSigningService().initializeCrossSigning(object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
promise.resume(bobAuthParams) promise.resume(bobAuthParams)
} }
}, it) } })
}
// Check that alice can see bob keys // Check that alice can see bob keys
val bobUserId = bobSession.myUserId val bobUserId = bobSession.myUserId
testHelper.runBlockingTest { aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true) } testHelper.runBlockingTest { aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true) }
val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobUserId) val bobKeysFromAlicePOV = testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobUserId)
}
assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false) assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false)
testHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().trustUser(bobUserId, it) } testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().trustUser(bobUserId)
}
// Now bobs logs in on a new device and verifies it // Now bobs logs in on a new device and verifies it
// We will want to test that in alice POV, this new device would be trusted by cross signing // We will want to test that in alice POV, this new device would be trusted by cross signing
@ -180,7 +202,9 @@ class XSigningTest : InstrumentedTest {
fail("Bob should see the new device") fail("Bob should see the new device")
} }
val bobSecondDevicePOVFirstDevice = bobSession.cryptoService().getDeviceInfo(bobUserId, bobSecondDeviceId) val bobSecondDevicePOVFirstDevice = runBlocking {
bobSession.cryptoService().getDeviceInfo(bobUserId, bobSecondDeviceId)
}
assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice) assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
// Manually mark it as trusted from first session // Manually mark it as trusted from first session
@ -198,7 +222,9 @@ class XSigningTest : InstrumentedTest {
fail("Alice should see the new device") fail("Alice should see the new device")
} }
val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null) val result = testHelper.runBlockingTest {
aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
}
assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified()) assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
testHelper.signOutAndClose(aliceSession) testHelper.signOutAndClose(aliceSession)

View File

@ -24,7 +24,6 @@ import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertTrue import junit.framework.TestCase.assertTrue
import junit.framework.TestCase.fail import junit.framework.TestCase.fail
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Assert import org.junit.Assert
import org.junit.FixMethodOrder import org.junit.FixMethodOrder
import org.junit.Ignore import org.junit.Ignore
@ -37,7 +36,6 @@ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -250,35 +248,34 @@ class KeyShareTests : InstrumentedTest {
aliceVerificationService1.addListener(object : VerificationService.Listener { aliceVerificationService1.addListener(object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
if (tx !is SasVerificationTransaction) return
Log.d("#TEST", "AA: tx incoming?:${tx.isIncoming} state ${tx.state}") Log.d("#TEST", "AA: tx incoming?:${tx.isIncoming} state ${tx.state}")
if (tx is SasVerificationTransaction) { when (tx.state) {
if (tx.state == VerificationTxState.OnStarted) { VerificationTxState.OnStarted -> commonTestHelper.runBlockingTest {
(tx as IncomingSasVerificationTransaction).performAccept() tx.acceptVerification()
} }
if (tx.state == VerificationTxState.ShortCodeReady) { VerificationTxState.ShortCodeReady -> commonTestHelper.runBlockingTest {
session1ShortCode = tx.getDecimalCodeRepresentation() session1ShortCode = tx.getDecimalCodeRepresentation()
commonTestHelper.runBlockingTest {
delay(500) delay(500)
tx.userHasVerifiedShortCode() tx.userHasVerifiedShortCode()
} }
} }
} }
} }
}) )
aliceVerificationService2.addListener(object : VerificationService.Listener { aliceVerificationService2.addListener(object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
if (tx !is SasVerificationTransaction) return
Log.d("#TEST", "BB: tx incoming?:${tx.isIncoming} state ${tx.state}") Log.d("#TEST", "BB: tx incoming?:${tx.isIncoming} state ${tx.state}")
if (tx is SasVerificationTransaction) { when (tx.state) {
if (tx.state == VerificationTxState.ShortCodeReady) { VerificationTxState.ShortCodeReady -> commonTestHelper.runBlockingTest {
session2ShortCode = tx.getDecimalCodeRepresentation() session2ShortCode = tx.getDecimalCodeRepresentation()
commonTestHelper.runBlockingTest {
delay(500) delay(500)
tx.userHasVerifiedShortCode() tx.userHasVerifiedShortCode()
} }
} }
} }
}
}) })
val txId = "m.testVerif12" val txId = "m.testVerif12"
@ -301,7 +298,8 @@ class KeyShareTests : InstrumentedTest {
// SSK and USK private keys should have been shared // SSK and USK private keys should have been shared
commonTestHelper.waitWithLatch(60_000) { latch -> commonTestHelper.waitWithLatch(60_000)
{ latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) { commonTestHelper.retryPeriodicallyWithLatch(latch) {
Log.d("#TEST", "CAN XS :${aliceSession2.cryptoService().crossSigningService().getMyCrossSigningKeys()}") Log.d("#TEST", "CAN XS :${aliceSession2.cryptoService().crossSigningService().getMyCrossSigningKeys()}")
aliceSession2.cryptoService().crossSigningService().canCrossSign() aliceSession2.cryptoService().crossSigningService().canCrossSign()
@ -309,7 +307,8 @@ class KeyShareTests : InstrumentedTest {
} }
// Test that key backup key has been shared to // Test that key backup key has been shared to
commonTestHelper.waitWithLatch(60_000) { latch -> commonTestHelper.waitWithLatch(60_000)
{ latch ->
val keysBackupService = aliceSession2.cryptoService().keysBackupService() val keysBackupService = aliceSession2.cryptoService().keysBackupService()
commonTestHelper.retryPeriodicallyWithLatch(latch) { commonTestHelper.retryPeriodicallyWithLatch(latch) {
Log.d("#TEST", "Recovery :${keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey}") Log.d("#TEST", "Recovery :${keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey}")

View File

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.verification
import android.util.Log import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
@ -32,9 +33,7 @@ import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.SasMode
import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -49,6 +48,8 @@ import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart
import org.matrix.android.sdk.internal.crypto.model.rest.toValue import org.matrix.android.sdk.internal.crypto.model.rest.toValue
import timber.log.Timber
import java.util.UUID
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@ -75,10 +76,15 @@ class SASTest : InstrumentedTest {
} }
bobVerificationService.addListener(bobListener) bobVerificationService.addListener(bobListener)
val txID = aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, val myDevice = testHelper.runBlockingTest {
bobSession.cryptoService().getMyDevice()
}
val txID = testHelper.runBlockingTest {
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS,
bobSession.myUserId, bobSession.myUserId,
bobSession.cryptoService().getMyDevice().deviceId, myDevice.deviceId,
null) null)
}
assertNotNull("Alice should have a started transaction", txID) assertNotNull("Alice should have a started transaction", txID)
val aliceKeyTx = aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID!!) val aliceKeyTx = aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID!!)
@ -90,16 +96,14 @@ class SASTest : InstrumentedTest {
val bobKeyTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID) val bobKeyTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID)
assertNotNull("Bob should have started verif transaction", bobKeyTx) assertNotNull("Bob should have started verif transaction", bobKeyTx)
assertTrue(bobKeyTx is SASDefaultVerificationTransaction) assertTrue(bobKeyTx is SasVerificationTransaction)
assertNotNull("Bob should have starting a SAS transaction", bobKeyTx) assertNotNull("Bob should have starting a SAS transaction", bobKeyTx)
assertTrue(aliceKeyTx is SASDefaultVerificationTransaction) assertTrue(aliceKeyTx is SasVerificationTransaction)
assertEquals("Alice and Bob have same transaction id", aliceKeyTx!!.transactionId, bobKeyTx!!.transactionId) assertEquals("Alice and Bob have same transaction id", aliceKeyTx!!.transactionId, bobKeyTx!!.transactionId)
val aliceSasTx = aliceKeyTx as SASDefaultVerificationTransaction?
val bobSasTx = bobKeyTx as SASDefaultVerificationTransaction?
assertEquals("Alice state should be started", VerificationTxState.Started, aliceSasTx!!.state) assertEquals("Alice state should be started", VerificationTxState.Started, aliceKeyTx.state)
assertEquals("Bob state should be started by alice", VerificationTxState.OnStarted, bobSasTx!!.state) assertEquals("Bob state should be started by alice", VerificationTxState.OnStarted, bobKeyTx.state)
// Let's cancel from alice side // Let's cancel from alice side
val cancelLatch = CountDownLatch(1) val cancelLatch = CountDownLatch(1)
@ -107,7 +111,7 @@ class SASTest : InstrumentedTest {
val bobListener2 = object : VerificationService.Listener { val bobListener2 = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
if (tx.transactionId == txID) { if (tx.transactionId == txID) {
val immutableState = (tx as SASDefaultVerificationTransaction).state val immutableState = (tx as SasVerificationTransaction).state
if (immutableState is VerificationTxState.Cancelled && !immutableState.byMe) { if (immutableState is VerificationTxState.Cancelled && !immutableState.byMe) {
cancelLatch.countDown() cancelLatch.countDown()
} }
@ -116,14 +120,16 @@ class SASTest : InstrumentedTest {
} }
bobVerificationService.addListener(bobListener2) bobVerificationService.addListener(bobListener2)
aliceSasTx.cancel(CancelCode.User) testHelper.runBlockingTest {
aliceKeyTx.cancel(CancelCode.User)
}
testHelper.await(cancelLatch) testHelper.await(cancelLatch)
assertTrue("Should be cancelled on alice side", aliceSasTx.state is VerificationTxState.Cancelled) assertTrue("Should be cancelled on alice side", aliceKeyTx.state is VerificationTxState.Cancelled)
assertTrue("Should be cancelled on bob side", bobSasTx.state is VerificationTxState.Cancelled) assertTrue("Should be cancelled on bob side", bobKeyTx.state is VerificationTxState.Cancelled)
val aliceCancelState = aliceSasTx.state as VerificationTxState.Cancelled val aliceCancelState = aliceKeyTx.state as VerificationTxState.Cancelled
val bobCancelState = bobSasTx.state as VerificationTxState.Cancelled val bobCancelState = bobKeyTx.state as VerificationTxState.Cancelled
assertTrue("Should be cancelled by me on alice side", aliceCancelState.byMe) assertTrue("Should be cancelled by me on alice side", aliceCancelState.byMe)
assertFalse("Should be cancelled by other on bob side", bobCancelState.byMe) assertFalse("Should be cancelled by other on bob side", bobCancelState.byMe)
@ -177,12 +183,16 @@ class SASTest : InstrumentedTest {
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
val aliceUserID = aliceSession.myUserId val aliceUserID = aliceSession.myUserId
val aliceDevice = aliceSession.cryptoService().getMyDevice().deviceId val aliceDevice = testHelper.runBlockingTest {
aliceSession.cryptoService().getMyDevice().deviceId
}
val aliceListener = object : VerificationService.Listener { val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
if ((tx as IncomingSasVerificationTransaction).uxState === IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT) { if (tx.state is VerificationTxState.OnStarted && tx is SasVerificationTransaction) {
(tx as IncomingSasVerificationTransaction).performAccept() testHelper.runBlockingTest {
tx.acceptVerification()
}
} }
} }
} }
@ -226,7 +236,9 @@ class SASTest : InstrumentedTest {
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
val aliceUserID = aliceSession.myUserId val aliceUserID = aliceSession.myUserId
val aliceDevice = aliceSession.cryptoService().getMyDevice().deviceId val aliceDevice = testHelper.runBlockingTest {
aliceSession.cryptoService().getMyDevice().deviceId
}
fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, mac = mac) fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, mac = mac)
@ -267,7 +279,9 @@ class SASTest : InstrumentedTest {
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
val aliceUserID = aliceSession.myUserId val aliceUserID = aliceSession.myUserId
val aliceDevice = aliceSession.cryptoService().getMyDevice().deviceId val aliceDevice = testHelper.runBlockingTest {
aliceSession.cryptoService().getMyDevice().deviceId
}
fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, codes = codes) fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, codes = codes)
@ -283,12 +297,15 @@ class SASTest : InstrumentedTest {
aliceUserID: String?, aliceUserID: String?,
aliceDevice: String?, aliceDevice: String?,
tid: String, tid: String,
protocols: List<String> = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS, protocols: List<String> = emptyList(),
hashes: List<String> = SASDefaultVerificationTransaction.KNOWN_HASHES, hashes: List<String> = emptyList(),
mac: List<String> = SASDefaultVerificationTransaction.KNOWN_MACS, mac: List<String> = emptyList(),
codes: List<String> = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES) { codes: List<String> = emptyList()) {
val deviceId = runBlocking {
bobSession.cryptoService().getMyDevice().deviceId
}
val startMessage = KeyVerificationStart( val startMessage = KeyVerificationStart(
fromDevice = bobSession.cryptoService().getMyDevice().deviceId, fromDevice = deviceId,
method = VerificationMethod.SAS.toValue(), method = VerificationMethod.SAS.toValue(),
transactionId = tid, transactionId = tid,
keyAgreementProtocols = protocols, keyAgreementProtocols = protocols,
@ -324,15 +341,15 @@ class SASTest : InstrumentedTest {
val aliceCreatedLatch = CountDownLatch(2) val aliceCreatedLatch = CountDownLatch(2)
val aliceCancelledLatch = CountDownLatch(2) val aliceCancelledLatch = CountDownLatch(2)
val createdTx = mutableListOf<SASDefaultVerificationTransaction>() val createdTx = mutableListOf<VerificationTransaction>()
val aliceListener = object : VerificationService.Listener { val aliceListener = object : VerificationService.Listener {
override fun transactionCreated(tx: VerificationTransaction) { override fun transactionCreated(tx: VerificationTransaction) {
createdTx.add(tx as SASDefaultVerificationTransaction) createdTx.add(tx)
aliceCreatedLatch.countDown() aliceCreatedLatch.countDown()
} }
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
if ((tx as SASDefaultVerificationTransaction).state is VerificationTxState.Cancelled && !(tx.state as VerificationTxState.Cancelled).byMe) { if (tx.state is VerificationTxState.Cancelled && !(tx.state as VerificationTxState.Cancelled).byMe) {
aliceCancelledLatch.countDown() aliceCancelledLatch.countDown()
} }
} }
@ -340,10 +357,13 @@ class SASTest : InstrumentedTest {
aliceVerificationService.addListener(aliceListener) aliceVerificationService.addListener(aliceListener)
val bobUserId = bobSession!!.myUserId val bobUserId = bobSession!!.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId val bobDeviceId = testHelper.runBlockingTest {
bobSession.cryptoService().getMyDevice().deviceId
}
testHelper.runBlockingTest {
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null) aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null) aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
}
testHelper.await(aliceCreatedLatch) testHelper.await(aliceCreatedLatch)
testHelper.await(aliceCancelledLatch) testHelper.await(aliceCancelledLatch)
@ -366,17 +386,10 @@ class SASTest : InstrumentedTest {
val aliceVerificationService = aliceSession.cryptoService().verificationService() val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService() val bobVerificationService = bobSession!!.cryptoService().verificationService()
var accepted: ValidVerificationInfoAccept? = null
var startReq: ValidVerificationInfoStart.SasVerificationInfoStart? = null
val aliceAcceptedLatch = CountDownLatch(1) val aliceAcceptedLatch = CountDownLatch(1)
val aliceListener = object : VerificationService.Listener { val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
Log.v("TEST", "== aliceTx state ${tx.state} => ${(tx as? OutgoingSasVerificationTransaction)?.uxState}") if (tx.state is VerificationTxState.OnAccepted) {
if ((tx as SASDefaultVerificationTransaction).state === VerificationTxState.OnAccepted) {
val at = tx as SASDefaultVerificationTransaction
accepted = at.accepted
startReq = at.startReq
aliceAcceptedLatch.countDown() aliceAcceptedLatch.countDown()
} }
} }
@ -385,32 +398,24 @@ class SASTest : InstrumentedTest {
val bobListener = object : VerificationService.Listener { val bobListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
Log.v("TEST", "== bobTx state ${tx.state} => ${(tx as? IncomingSasVerificationTransaction)?.uxState}") if (tx.state is VerificationTxState.OnStarted && tx is SasVerificationTransaction) {
if ((tx as IncomingSasVerificationTransaction).uxState === IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT) {
bobVerificationService.removeListener(this) bobVerificationService.removeListener(this)
val at = tx as IncomingSasVerificationTransaction testHelper.runBlockingTest {
at.performAccept() tx.acceptVerification()
}
} }
} }
} }
bobVerificationService.addListener(bobListener) bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId val bobUserId = bobSession.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId val bobDeviceId = runBlocking {
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null) bobSession.cryptoService().getMyDevice().deviceId
testHelper.await(aliceAcceptedLatch)
assertTrue("Should have receive a commitment", accepted!!.commitment?.trim()?.isEmpty() == false)
// check that agreement is valid
assertTrue("Agreed Protocol should be Valid", accepted != null)
assertTrue("Agreed Protocol should be known by alice", startReq!!.keyAgreementProtocols.contains(accepted!!.keyAgreementProtocol))
assertTrue("Hash should be known by alice", startReq!!.hashes.contains(accepted!!.hash))
assertTrue("Hash should be known by alice", startReq!!.messageAuthenticationCodes.contains(accepted!!.messageAuthenticationCode))
accepted!!.shortAuthenticationStrings.forEach {
assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings.contains(it))
} }
testHelper.runBlockingTest {
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
}
testHelper.await(aliceAcceptedLatch)
cryptoTestData.cleanUp(testHelper) cryptoTestData.cleanUp(testHelper)
} }
@ -422,17 +427,19 @@ class SASTest : InstrumentedTest {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession val bobSession = cryptoTestData.secondSession!!
cryptoTestHelper.initializeCrossSigning(aliceSession)
cryptoTestHelper.initializeCrossSigning(bobSession)
val aliceVerificationService = aliceSession.cryptoService().verificationService() val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService() val bobVerificationService = bobSession.cryptoService().verificationService()
val aliceSASLatch = CountDownLatch(1) val aliceSASLatch = CountDownLatch(1)
val aliceListener = object : VerificationService.Listener { val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as OutgoingSasVerificationTransaction).uxState when (tx.state) {
when (uxState) { VerificationTxState.ShortCodeReady -> {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
aliceSASLatch.countDown() aliceSASLatch.countDown()
} }
else -> Unit else -> Unit
@ -443,32 +450,42 @@ class SASTest : InstrumentedTest {
val bobSASLatch = CountDownLatch(1) val bobSASLatch = CountDownLatch(1)
val bobListener = object : VerificationService.Listener { val bobListener = object : VerificationService.Listener {
override fun verificationRequestCreated(pr: PendingVerificationRequest) {
}
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as IncomingSasVerificationTransaction).uxState val sasVerification = tx as SasVerificationTransaction
when (uxState) { when (tx.state) {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> { VerificationTxState.OnStarted -> testHelper.runBlockingTest {
tx.performAccept() sasVerification.acceptVerification()
}
VerificationTxState.ShortCodeReady -> {
bobSASLatch.countDown()
} }
else -> Unit else -> Unit
} }
if (uxState === IncomingSasVerificationTransaction.UxState.SHOW_SAS) {
bobSASLatch.countDown()
}
} }
} }
bobVerificationService.addListener(bobListener) bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId val bobUserId = bobSession.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId testHelper.runBlockingTest {
val verificationSAS = aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null) aliceSession.cryptoService().downloadKeys(listOf(bobUserId), forceDownload = true)
aliceVerificationService.requestKeyVerificationInDMs(listOf(VerificationMethod.SAS),bobUserId, cryptoTestData.roomId)
}
testHelper.await(aliceSASLatch) testHelper.await(aliceSASLatch)
testHelper.await(bobSASLatch) testHelper.await(bobSASLatch)
val aliceTx = aliceVerificationService.getExistingTransaction(bobUserId, verificationSAS!!) as SASDefaultVerificationTransaction /*
val bobTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, verificationSAS) as SASDefaultVerificationTransaction val aliceTx = aliceVerificationService.getExistingTransaction(bobUserId, verificationSAS!!) as SasVerificationTransaction
val bobTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, verificationSAS) as SasVerificationTransaction
assertEquals("Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL),
bobTx.getShortCodeRepresentation(SasMode.DECIMAL)) assertEquals("Should have same SAS", aliceTx.getDecimalCodeRepresentation(), bobTx.getDecimalCodeRepresentation())
*/
cryptoTestData.cleanUp(testHelper) cryptoTestData.cleanUp(testHelper)
} }
@ -489,13 +506,12 @@ class SASTest : InstrumentedTest {
val aliceListener = object : VerificationService.Listener { val aliceListener = object : VerificationService.Listener {
var matchOnce = true var matchOnce = true
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as OutgoingSasVerificationTransaction).uxState if (tx !is SasVerificationTransaction) return
Log.v("TEST", "== aliceState ${uxState.name}") when (tx.state) {
when (uxState) { VerificationTxState.ShortCodeReady -> testHelper.runBlockingTest {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
tx.userHasVerifiedShortCode() tx.userHasVerifiedShortCode()
} }
OutgoingSasVerificationTransaction.UxState.VERIFIED -> { VerificationTxState.Verified -> {
if (matchOnce) { if (matchOnce) {
matchOnce = false matchOnce = false
aliceSASLatch.countDown() aliceSASLatch.countDown()
@ -512,22 +528,21 @@ class SASTest : InstrumentedTest {
var acceptOnce = true var acceptOnce = true
var matchOnce = true var matchOnce = true
override fun transactionUpdated(tx: VerificationTransaction) { override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as IncomingSasVerificationTransaction).uxState if (tx !is SasVerificationTransaction) return
Log.v("TEST", "== bobState ${uxState.name}") when (tx.state) {
when (uxState) { VerificationTxState.OnStarted -> testHelper.runBlockingTest {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
if (acceptOnce) { if (acceptOnce) {
acceptOnce = false acceptOnce = false
tx.performAccept() tx.acceptVerification()
} }
} }
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> { VerificationTxState.ShortCodeReady -> testHelper.runBlockingTest {
if (matchOnce) { if (matchOnce) {
matchOnce = false matchOnce = false
tx.userHasVerifiedShortCode() tx.userHasVerifiedShortCode()
} }
} }
IncomingSasVerificationTransaction.UxState.VERIFIED -> { VerificationTxState.Verified -> {
bobSASLatch.countDown() bobSASLatch.countDown()
} }
else -> Unit else -> Unit
@ -537,15 +552,22 @@ class SASTest : InstrumentedTest {
bobVerificationService.addListener(bobListener) bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId val bobUserId = bobSession.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId val bobDeviceId = runBlocking {
bobSession.cryptoService().getMyDevice().deviceId
}
testHelper.runBlockingTest {
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null) aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
}
testHelper.await(aliceSASLatch) testHelper.await(aliceSASLatch)
testHelper.await(bobSASLatch) testHelper.await(bobSASLatch)
// Assert that devices are verified // Assert that devices are verified
val bobDeviceInfoFromAlicePOV: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(bobUserId, bobDeviceId) val bobDeviceInfoFromAlicePOV: CryptoDeviceInfo? = testHelper.runBlockingTest {
val aliceDeviceInfoFromBobPOV: CryptoDeviceInfo? = bobSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId) aliceSession.cryptoService().getDeviceInfo(bobUserId, bobDeviceId)
}
val aliceDeviceInfoFromBobPOV: CryptoDeviceInfo? = testHelper.runBlockingTest {
bobSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId)
}
assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified) assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified)
assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified) assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified)
cryptoTestData.cleanUp(testHelper) cryptoTestData.cleanUp(testHelper)
@ -563,11 +585,13 @@ class SASTest : InstrumentedTest {
val aliceVerificationService = aliceSession.cryptoService().verificationService() val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService() val bobVerificationService = bobSession!!.cryptoService().verificationService()
val req = aliceVerificationService.requestKeyVerificationInDMs( val req = testHelper.runBlockingTest {
aliceVerificationService.requestKeyVerificationInDMs(
listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW),
bobSession.myUserId, bobSession.myUserId,
cryptoTestData.roomId cryptoTestData.roomId
) )
}
var requestID: String? = null var requestID: String? = null
@ -590,11 +614,13 @@ class SASTest : InstrumentedTest {
} }
} }
testHelper.runBlockingTest {
bobVerificationService.readyPendingVerification( bobVerificationService.readyPendingVerification(
listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW),
aliceSession.myUserId, aliceSession.myUserId,
requestID!! requestID!!
) )
}
// wait for alice to get the ready // wait for alice to get the ready
testHelper.waitWithLatch { testHelper.waitWithLatch {
@ -606,6 +632,7 @@ class SASTest : InstrumentedTest {
} }
// Start concurrent! // Start concurrent!
testHelper.runBlockingTest {
aliceVerificationService.beginKeyVerificationInDMs( aliceVerificationService.beginKeyVerificationInDMs(
VerificationMethod.SAS, VerificationMethod.SAS,
requestID!!, requestID!!,
@ -620,6 +647,8 @@ class SASTest : InstrumentedTest {
aliceSession.myUserId, aliceSession.myUserId,
aliceSession.sessionParams.deviceId!!) aliceSession.sessionParams.deviceId!!)
}
// we should reach SHOW SAS on both // we should reach SHOW SAS on both
var alicePovTx: SasVerificationTransaction? var alicePovTx: SasVerificationTransaction?
var bobPovTx: SasVerificationTransaction? var bobPovTx: SasVerificationTransaction?

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2020 The Matrix.org Foundation C.I.C. * Copyright (c) 2022 New Vector Ltd
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.matrix.android.sdk.internal.crypto.verification.qrcode package org.matrix.android.sdk.internal.crypto.verification
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBe
@ -23,19 +23,13 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.junit.runners.MethodSorters import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.TestConstants import timber.log.Timber
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM) @FixMethodOrder(MethodSorters.JVM)
@ -147,8 +141,6 @@ class VerificationTest : InstrumentedTest {
ExpectedResult(sasIsSupported = true, otherCanShowQrCode = true, otherCanScanQrCode = true) ExpectedResult(sasIsSupported = true, otherCanShowQrCode = true, otherCanScanQrCode = true)
) )
// TODO Add tests without SAS
private fun doTest(aliceSupportedMethods: List<VerificationMethod>, private fun doTest(aliceSupportedMethods: List<VerificationMethod>,
bobSupportedMethods: List<VerificationMethod>, bobSupportedMethods: List<VerificationMethod>,
expectedResultForAlice: ExpectedResult, expectedResultForAlice: ExpectedResult,
@ -160,37 +152,8 @@ class VerificationTest : InstrumentedTest {
val aliceSession = cryptoTestData.firstSession val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession!! val bobSession = cryptoTestData.secondSession!!
testHelper.doSync<Unit> { callback -> cryptoTestHelper.initializeCrossSigning(aliceSession)
aliceSession.cryptoService().crossSigningService() cryptoTestHelper.initializeCrossSigning(bobSession)
.initializeCrossSigning(
object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
promise.resume(
UserPasswordAuth(
user = aliceSession.myUserId,
password = TestConstants.PASSWORD,
session = flowResponse.session
)
)
}
}, callback)
}
testHelper.doSync<Unit> { callback ->
bobSession.cryptoService().crossSigningService()
.initializeCrossSigning(
object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
promise.resume(
UserPasswordAuth(
user = bobSession.myUserId,
password = TestConstants.PASSWORD,
session = flowResponse.session
)
)
}
}, callback)
}
val aliceVerificationService = aliceSession.cryptoService().verificationService() val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession.cryptoService().verificationService() val bobVerificationService = bobSession.cryptoService().verificationService()
@ -202,6 +165,7 @@ class VerificationTest : InstrumentedTest {
val aliceListener = object : VerificationService.Listener { val aliceListener = object : VerificationService.Listener {
override fun verificationRequestUpdated(pr: PendingVerificationRequest) { override fun verificationRequestUpdated(pr: PendingVerificationRequest) {
// Step 4: Alice receive the ready request // Step 4: Alice receive the ready request
Timber.v("Alice is ready: ${pr.isReady}")
if (pr.isReady) { if (pr.isReady) {
aliceReadyPendingVerificationRequest = pr aliceReadyPendingVerificationRequest = pr
latch.countDown() latch.countDown()
@ -213,16 +177,19 @@ class VerificationTest : InstrumentedTest {
val bobListener = object : VerificationService.Listener { val bobListener = object : VerificationService.Listener {
override fun verificationRequestCreated(pr: PendingVerificationRequest) { override fun verificationRequestCreated(pr: PendingVerificationRequest) {
// Step 2: Bob accepts the verification request // Step 2: Bob accepts the verification request
bobVerificationService.readyPendingVerificationInDMs( Timber.v("Bob accepts the verification request")
testHelper.runBlockingTest {
bobVerificationService.readyPendingVerification(
bobSupportedMethods, bobSupportedMethods,
aliceSession.myUserId, aliceSession.myUserId,
cryptoTestData.roomId,
pr.transactionId!! pr.transactionId!!
) )
} }
}
override fun verificationRequestUpdated(pr: PendingVerificationRequest) { override fun verificationRequestUpdated(pr: PendingVerificationRequest) {
// Step 3: Bob is ready // Step 3: Bob is ready
Timber.v("Bob is ready: ${pr.isReady}")
if (pr.isReady) { if (pr.isReady) {
bobReadyPendingVerificationRequest = pr bobReadyPendingVerificationRequest = pr
latch.countDown() latch.countDown()
@ -233,7 +200,9 @@ class VerificationTest : InstrumentedTest {
val bobUserId = bobSession.myUserId val bobUserId = bobSession.myUserId
// Step 1: Alice starts a verification request // Step 1: Alice starts a verification request
testHelper.runBlockingTest {
aliceVerificationService.requestKeyVerificationInDMs(aliceSupportedMethods, bobUserId, cryptoTestData.roomId) aliceVerificationService.requestKeyVerificationInDMs(aliceSupportedMethods, bobUserId, cryptoTestData.roomId)
}
testHelper.await(latch) testHelper.await(latch)
aliceReadyPendingVerificationRequest!!.let { pr -> aliceReadyPendingVerificationRequest!!.let { pr ->

View File

@ -1,46 +0,0 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldNotBeEqualTo
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class SharedSecretTest : InstrumentedTest {
@Test
fun testSharedSecretLengthCase() {
repeat(100) {
generateSharedSecretV2().length shouldBe 11
}
}
@Test
fun testSharedDiffCase() {
val sharedSecret1 = generateSharedSecretV2()
val sharedSecret2 = generateSharedSecretV2()
sharedSecret1 shouldNotBeEqualTo sharedSecret2
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.crypto.verification
interface IncomingSasVerificationTransaction : SasVerificationTransaction {
val uxState: UxState
fun performAccept()
enum class UxState {
UNKNOWN,
SHOW_ACCEPT,
WAIT_FOR_KEY_AGREEMENT,
SHOW_SAS,
WAIT_FOR_VERIFICATION,
VERIFIED,
CANCELLED_BY_ME,
CANCELLED_BY_OTHER
}
}

View File

@ -1,32 +0,0 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.session.crypto.verification
interface OutgoingSasVerificationTransaction : SasVerificationTransaction {
val uxState: UxState
enum class UxState {
UNKNOWN,
WAIT_FOR_START,
WAIT_FOR_KEY_AGREEMENT,
SHOW_SAS,
WAIT_FOR_VERIFICATION,
VERIFIED,
CANCELLED_BY_ME,
CANCELLED_BY_OTHER
}
}

View File

@ -46,55 +46,38 @@ interface VerificationService {
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest? fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
suspend fun beginKeyVerification(method: VerificationMethod,
otherUserId: String,
otherDeviceId: String,
transactionId: String?): String?
/** /**
* Request key verification with another user via room events (instead of the to-device API) * Request key verification with another user via room events (instead of the to-device API).
*/ */
suspend fun requestKeyVerificationInDMs(methods: List<VerificationMethod>, suspend fun requestKeyVerificationInDMs(methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
roomId: String, roomId: String,
localId: String? = LocalEcho.createLocalEchoId()): PendingVerificationRequest localId: String? = LocalEcho.createLocalEchoId()): PendingVerificationRequest
suspend fun cancelVerificationRequest(request: PendingVerificationRequest)
/** /**
* Request a key verification from another user using toDevice events. * Request a self key verification using to-device API (instead of room events).
*/ */
suspend fun requestKeyVerification(methods: List<VerificationMethod>, suspend fun requestSelfKeyVerification(methods: List<VerificationMethod>): PendingVerificationRequest
otherUserId: String,
otherDevices: List<String>?): PendingVerificationRequest
suspend fun declineVerificationRequestInDMs(otherUserId: String,
transactionId: String,
roomId: String)
// Only SAS method is supported for the moment
// TODO Parameter otherDeviceId should be removed in this case
suspend fun beginKeyVerificationInDMs(method: VerificationMethod,
transactionId: String,
roomId: String,
otherUserId: String,
otherDeviceId: String): String
/** /**
* Returns false if the request is unknown * You should call this method after receiving a verification request.
*/ * Accept the verification request advertising the given methods as supported
suspend fun readyPendingVerificationInDMs(methods: List<VerificationMethod>, * Returns false if the request is unknown or transaction is not ready.
otherUserId: String,
roomId: String,
transactionId: String): Boolean
/**
* Returns false if the request is unknown
*/ */
suspend fun readyPendingVerification(methods: List<VerificationMethod>, suspend fun readyPendingVerification(methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
transactionId: String): Boolean transactionId: String): Boolean
suspend fun cancelVerificationRequest(request: PendingVerificationRequest)
suspend fun cancelVerificationRequest(otherUserId: String, transactionId: String)
suspend fun beginKeyVerification(method: VerificationMethod,
otherUserId: String,
transactionId: String): String?
suspend fun beginDeviceVerification(otherUserId: String, otherDeviceId: String): String?
interface Listener { interface Listener {
/** /**
* Called when a verification request is created either by the user, or by the other user. * Called when a verification request is created either by the user, or by the other user.

View File

@ -775,7 +775,7 @@ internal class DefaultCryptoService @Inject constructor(
} }
} }
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO | doKeyDownloadForUsers(): error") Timber.tag(loggerTag.value).e(throwable, "## CRYPTO doKeyDownloadForUsers(): error")
} }
} }

View File

@ -229,17 +229,12 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return null return null
} }
override suspend fun requestKeyVerification( override suspend fun requestSelfKeyVerification(methods: List<VerificationMethod>): PendingVerificationRequest {
methods: List<VerificationMethod>, val verification = when (val identity = olmMachine.getIdentity(olmMachine.userId())) {
otherUserId: String,
otherDevices: List<String>?
): PendingVerificationRequest {
val verification = when (val identity = olmMachine.getIdentity(otherUserId)) {
is OwnUserIdentity -> identity.requestVerification(methods) is OwnUserIdentity -> identity.requestVerification(methods)
is UserIdentity -> throw IllegalArgumentException("This method doesn't support verification of other users devices") is UserIdentity -> throw IllegalArgumentException("This method doesn't support verification of other users devices")
null -> throw IllegalArgumentException("Cross signing has not been bootstrapped for our own user") null -> throw IllegalArgumentException("Cross signing has not been bootstrapped for our own user")
} }
return verification.toPendingVerificationRequest() return verification.toPendingVerificationRequest()
} }
@ -249,7 +244,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
roomId: String, roomId: String,
localId: String? localId: String?
): PendingVerificationRequest { ): PendingVerificationRequest {
Timber.i("## SAS Requesting verification to user: $otherUserId in room $roomId") olmMachine.ensureUsersKeys(listOf(otherUserId))
val verification = when (val identity = olmMachine.getIdentity(otherUserId)) { val verification = when (val identity = olmMachine.getIdentity(otherUserId)) {
is UserIdentity -> identity.requestVerification(methods, roomId, localId!!) is UserIdentity -> identity.requestVerification(methods, roomId, localId!!)
is OwnUserIdentity -> throw IllegalArgumentException("This method doesn't support verification of our own user") is OwnUserIdentity -> throw IllegalArgumentException("This method doesn't support verification of our own user")
@ -284,23 +279,12 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
} }
} }
override suspend fun readyPendingVerificationInDMs(
methods: List<VerificationMethod>,
otherUserId: String,
roomId: String,
transactionId: String
): Boolean {
return readyPendingVerification(methods, otherUserId, transactionId)
}
override suspend fun beginKeyVerification( override suspend fun beginKeyVerification(
method: VerificationMethod, method: VerificationMethod,
otherUserId: String, otherUserId: String,
otherDeviceId: String, transactionId: String
transactionId: String?
): String? { ): String? {
return if (method == VerificationMethod.SAS) { return if (method == VerificationMethod.SAS) {
if (transactionId != null) {
val request = olmMachine.getVerificationRequest(otherUserId, transactionId) val request = olmMachine.getVerificationRequest(otherUserId, transactionId)
val sas = request?.startSasVerification() val sas = request?.startSasVerification()
@ -312,6 +296,11 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
null null
} }
} else { } else {
throw IllegalArgumentException("Unknown verification method")
}
}
override suspend fun beginDeviceVerification(otherUserId: String, otherDeviceId: String): String? {
// This starts the short SAS flow, the one that doesn't start with // This starts the short SAS flow, the one that doesn't start with
// a `m.key.verification.request`, Element web stopped doing this, might // a `m.key.verification.request`, Element web stopped doing this, might
// be wise do do so as well // be wise do do so as well
@ -319,43 +308,20 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
// triggers this is called `manuallyVerify()` // triggers this is called `manuallyVerify()`
val otherDevice = olmMachine.getDevice(otherUserId, otherDeviceId) val otherDevice = olmMachine.getDevice(otherUserId, otherDeviceId)
val verification = otherDevice?.startVerification() val verification = otherDevice?.startVerification()
if (verification != null) { return if (verification != null) {
dispatcher.dispatchTxAdded(verification) dispatcher.dispatchTxAdded(verification)
verification.transactionId verification.transactionId
} else { } else {
null null
} }
} }
} else {
throw IllegalArgumentException("Unknown verification method")
}
}
override suspend fun beginKeyVerificationInDMs(
method: VerificationMethod,
transactionId: String,
roomId: String,
otherUserId: String,
otherDeviceId: String
): String {
beginKeyVerification(method, otherUserId, otherDeviceId, transactionId)
// TODO what's the point of returning the same ID we got as an argument?
// We do this because the old verification service did so
return transactionId
}
override suspend fun cancelVerificationRequest(request: PendingVerificationRequest) { override suspend fun cancelVerificationRequest(request: PendingVerificationRequest) {
val verificationRequest = request.transactionId?.let { request.transactionId ?: return
olmMachine.getVerificationRequest(request.otherUserId, it) cancelVerificationRequest(request.otherUserId, request.transactionId)
}
verificationRequest?.cancel()
} }
override suspend fun declineVerificationRequestInDMs( override suspend fun cancelVerificationRequest(otherUserId: String, transactionId: String) {
otherUserId: String,
transactionId: String,
roomId: String
) {
val verificationRequest = olmMachine.getVerificationRequest(otherUserId, transactionId) val verificationRequest = olmMachine.getVerificationRequest(otherUserId, transactionId)
verificationRequest?.cancel() verificationRequest?.cancel()
} }

View File

@ -1,29 +0,0 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.crypto.verification.qrcode
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
import java.security.SecureRandom
fun generateSharedSecretV2(): String {
val secureRandom = SecureRandom()
// 8 bytes long
val secretBytes = ByteArray(8)
secureRandom.nextBytes(secretBytes)
return secretBytes.toBase64NoPadding()
}

View File

@ -51,6 +51,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
import org.matrix.android.sdk.common.CommonTestHelper
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import kotlin.coroutines.resume import kotlin.coroutines.resume
@ -134,10 +135,8 @@ class VerifySessionInteractiveTest : VerificationTestBase() {
onView(withId(R.id.bottomSheetFragmentContainer)) onView(withId(R.id.bottomSheetFragmentContainer))
.check(matches(not(hasDescendant(withText(R.string.verification_cannot_access_other_session))))) .check(matches(not(hasDescendant(withText(R.string.verification_cannot_access_other_session)))))
val request = existingSession!!.cryptoService().verificationService().requestKeyVerification( val request = existingSession!!.cryptoService().verificationService().requestSelfKeyVerification(
listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW)
existingSession!!.myUserId,
listOf(uiSession.sessionParams.deviceId!!)
) )
val transactionId = request.transactionId!! val transactionId = request.transactionId!!

View File

@ -166,9 +166,8 @@ class IncomingVerificationRequestHandler @Inject constructor(
} }
} }
dismissedAction = LaunchCoroutineRunnable(coroutineScope) { dismissedAction = LaunchCoroutineRunnable(coroutineScope) {
session?.cryptoService()?.verificationService()?.declineVerificationRequestInDMs(pr.otherUserId, session?.cryptoService()?.verificationService()?.cancelVerificationRequest(pr.otherUserId,
pr.transactionId ?: "", pr.transactionId ?: ""
pr.roomId ?: ""
) )
} }
colorAttribute = R.attr.vctr_notice_secondary colorAttribute = R.attr.vctr_notice_secondary

View File

@ -238,7 +238,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
handleRequestVerificationByDM(roomId, otherUserId) handleRequestVerificationByDM(roomId, otherUserId)
} }
is VerificationAction.StartSASVerification -> { is VerificationAction.StartSASVerification -> {
handleStartSASVerification(roomId, otherUserId, action) handleStartSASVerification(otherUserId, action)
} }
is VerificationAction.RemoteQrCodeScanned -> { is VerificationAction.RemoteQrCodeScanned -> {
handleRemoteQrCodeScanned(action) handleRemoteQrCodeScanned(action)
@ -284,27 +284,15 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
}.exhaustive }.exhaustive
} }
private fun handleStartSASVerification(roomId: String?, otherUserId: String, action: VerificationAction.StartSASVerification) { private fun handleStartSASVerification(otherUserId: String, action: VerificationAction.StartSASVerification) {
val request = session.cryptoService().verificationService().getExistingVerificationRequest(otherUserId, action.pendingRequestTransactionId) val request = session.cryptoService().verificationService().getExistingVerificationRequest(otherUserId, action.pendingRequestTransactionId)
?: return ?: return
val otherDevice = if (request.isIncoming) request.requestInfo?.fromDevice else request.readyInfo?.fromDevice
viewModelScope.launch { viewModelScope.launch {
if (roomId == null) {
session.cryptoService().verificationService().beginKeyVerification( session.cryptoService().verificationService().beginKeyVerification(
VerificationMethod.SAS, VerificationMethod.SAS,
otherUserId = request.otherUserId, otherUserId = request.otherUserId,
otherDeviceId = otherDevice ?: "",
transactionId = action.pendingRequestTransactionId transactionId = action.pendingRequestTransactionId
) )
} else {
session.cryptoService().verificationService().beginKeyVerificationInDMs(
VerificationMethod.SAS,
transactionId = action.pendingRequestTransactionId,
roomId = roomId,
otherUserId = request.otherUserId,
otherDeviceId = otherDevice ?: ""
)
}
} }
} }

View File

@ -995,10 +995,9 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) { private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) {
Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}") Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}")
viewModelScope.launch { viewModelScope.launch {
if (session.cryptoService().verificationService().readyPendingVerificationInDMs( if (session.cryptoService().verificationService().readyPendingVerification(
supportedVerificationMethodsProvider.provide(), supportedVerificationMethodsProvider.provide(),
action.otherUserId, action.otherUserId,
room.roomId,
action.transactionId)) { action.transactionId)) {
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action)) _viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
} else { } else {
@ -1009,10 +1008,9 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleDeclineVerification(action: RoomDetailAction.DeclineVerificationRequest) { private fun handleDeclineVerification(action: RoomDetailAction.DeclineVerificationRequest) {
viewModelScope.launch { viewModelScope.launch {
session.cryptoService().verificationService().declineVerificationRequestInDMs( session.cryptoService().verificationService().cancelVerificationRequest(
action.otherUserId, action.otherUserId,
action.transactionId, action.transactionId)
room.roomId)
} }
} }

View File

@ -217,10 +217,8 @@ class DefaultNavigator @Inject constructor(
override fun requestSessionVerification(context: Context, otherSessionId: String) { override fun requestSessionVerification(context: Context, otherSessionId: String) {
coroutineScope.launch { coroutineScope.launch {
val session = sessionHolder.getSafeActiveSession() ?: return@launch val session = sessionHolder.getSafeActiveSession() ?: return@launch
val pr = session.cryptoService().verificationService().requestKeyVerification( val pr = session.cryptoService().verificationService().requestSelfKeyVerification(
supportedVerificationMethodsProvider.provide(), supportedVerificationMethodsProvider.provide()
session.myUserId,
listOf(otherSessionId)
) )
if (context is AppCompatActivity) { if (context is AppCompatActivity) {
VerificationBottomSheet.withArgs( VerificationBottomSheet.withArgs(
@ -241,10 +239,8 @@ class DefaultNavigator @Inject constructor(
.map { it.deviceId } .map { it.deviceId }
if (context is AppCompatActivity) { if (context is AppCompatActivity) {
if (otherSessions.isNotEmpty()) { if (otherSessions.isNotEmpty()) {
val pr = session.cryptoService().verificationService().requestKeyVerification( val pr = session.cryptoService().verificationService().requestSelfKeyVerification(
supportedVerificationMethodsProvider.provide(), supportedVerificationMethodsProvider.provide())
session.myUserId,
otherSessions)
VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId) VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG) .show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
} else { } else {

View File

@ -126,11 +126,10 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) { private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) {
if (!initialState.allowDeviceAction) return if (!initialState.allowDeviceAction) return
viewModelScope.launch { viewModelScope.launch {
session.cryptoService().verificationService().beginKeyVerification( session.cryptoService().verificationService().beginDeviceVerification(
method = VerificationMethod.SAS,
otherUserId = initialState.userId, otherUserId = initialState.userId,
otherDeviceId = action.deviceId, otherDeviceId = action.deviceId,
transactionId = null)?.let { txID -> )?.let { txID ->
_viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID)) _viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID))
} }
} }

View File

@ -250,7 +250,7 @@ class DevicesViewModel @AssistedInject constructor(
viewModelScope.launch { viewModelScope.launch {
val txID = session.cryptoService() val txID = session.cryptoService()
.verificationService() .verificationService()
.beginKeyVerification(VerificationMethod.SAS, session.myUserId, action.deviceId, null) .beginDeviceVerification(session.myUserId, action.deviceId)
_viewEvents.post(DevicesViewEvents.ShowVerifyDevice( _viewEvents.post(DevicesViewEvents.ShowVerifyDevice(
session.myUserId, session.myUserId,
txID txID