crypto: Allow the displaying of QR codes
This commit is contained in:
parent
d15269a4bd
commit
6523ca5afe
@ -16,6 +16,8 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import java.io.File
|
||||
@ -26,10 +28,16 @@ import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
@ -45,11 +53,14 @@ import uniffi.olm.Device
|
||||
import uniffi.olm.DeviceLists
|
||||
import uniffi.olm.KeyRequestPair
|
||||
import uniffi.olm.Logger
|
||||
import uniffi.olm.OutgoingVerificationRequest
|
||||
import uniffi.olm.QrCode
|
||||
import uniffi.olm.OlmMachine as InnerMachine
|
||||
import uniffi.olm.ProgressListener as RustProgressListener
|
||||
import uniffi.olm.Request
|
||||
import uniffi.olm.RequestType
|
||||
import uniffi.olm.Sas
|
||||
import uniffi.olm.Verification
|
||||
import uniffi.olm.VerificationRequest
|
||||
import uniffi.olm.setLogger
|
||||
|
||||
class CryptoLogger : Logger {
|
||||
@ -117,6 +128,136 @@ internal class DeviceUpdateObserver {
|
||||
}
|
||||
}
|
||||
|
||||
internal class QrCodeVerification(
|
||||
private val machine: uniffi.olm.OlmMachine,
|
||||
private var inner: QrCode,
|
||||
private val sender: RequestSender,
|
||||
private val listeners: ArrayList<VerificationService.Listener>,
|
||||
) : QrCodeVerificationTransaction {
|
||||
private val uiHandler = Handler(Looper.getMainLooper())
|
||||
private var stateField: VerificationTxState = VerificationTxState.OnStarted
|
||||
|
||||
private fun dispatchTxUpdated() {
|
||||
uiHandler.post {
|
||||
listeners.forEach {
|
||||
try {
|
||||
it.transactionUpdated(this)
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "## Error while notifying listeners")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val qrCodeText: String?
|
||||
get() {
|
||||
val data = this.machine.generateQrCode(this.inner.otherUserId, this.inner.flowId)
|
||||
|
||||
// TODO Why are we encoding this to ISO_8859_1? If we're going to encode, why not base64?
|
||||
return data?.fromBase64()?.toString(Charsets.ISO_8859_1)
|
||||
}
|
||||
|
||||
override fun userHasScannedOtherQrCode(otherQrCodeText: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun otherUserScannedMyQrCode() {
|
||||
val request = runBlocking { confirm() } ?: return
|
||||
sendRequest(request)
|
||||
}
|
||||
|
||||
override fun otherUserDidNotScannedMyQrCode() {
|
||||
// TODO Is this code correct here? The old code seems to do this
|
||||
cancelHelper(CancelCode.MismatchedKeys)
|
||||
}
|
||||
|
||||
override var state: VerificationTxState
|
||||
get() {
|
||||
refreshData()
|
||||
val state = when {
|
||||
this.inner.isDone -> VerificationTxState.Verified
|
||||
this.inner.otherSideScanned -> VerificationTxState.QrScannedByOther
|
||||
this.inner.isCancelled -> {
|
||||
val cancelCode = safeValueOf(this.inner.cancelCode)
|
||||
val byMe = this.inner.cancelledByUs ?: false
|
||||
VerificationTxState.Cancelled(cancelCode, byMe)
|
||||
}
|
||||
else -> {
|
||||
VerificationTxState.None
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
set(value) {}
|
||||
|
||||
override val transactionId: String
|
||||
get() = this.inner.flowId
|
||||
|
||||
override val otherUserId: String
|
||||
get() = this.inner.otherUserId
|
||||
|
||||
override var otherDeviceId: String?
|
||||
get() = this.inner.otherDeviceId
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
set(value) {}
|
||||
|
||||
override val isIncoming: Boolean
|
||||
get() = !this.inner.weStarted
|
||||
|
||||
override fun cancel() {
|
||||
cancelHelper(CancelCode.User)
|
||||
}
|
||||
|
||||
override fun cancel(code: CancelCode) {
|
||||
cancelHelper(code)
|
||||
}
|
||||
|
||||
override fun isToDeviceTransport(): Boolean {
|
||||
return this.inner.roomId == null
|
||||
}
|
||||
|
||||
@Throws(CryptoStoreErrorException::class)
|
||||
suspend fun confirm(): OutgoingVerificationRequest? =
|
||||
withContext(Dispatchers.IO) {
|
||||
machine.confirmVerification(inner.otherUserId, inner.flowId)
|
||||
}
|
||||
|
||||
private fun sendRequest(request: OutgoingVerificationRequest) {
|
||||
runBlocking {
|
||||
when (request) {
|
||||
is OutgoingVerificationRequest.ToDevice -> {
|
||||
sender.sendToDevice(request.eventType, request.body)
|
||||
}
|
||||
is OutgoingVerificationRequest.InRoom -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
refreshData()
|
||||
dispatchTxUpdated()
|
||||
}
|
||||
|
||||
private fun cancelHelper(code: CancelCode) {
|
||||
val request = this.machine.cancelVerification(this.inner.otherUserId, inner.flowId, code.value)
|
||||
|
||||
if (request != null) {
|
||||
sendRequest(request)
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshData() {
|
||||
when (val verification = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)) {
|
||||
is Verification.QrCodeV1 -> {
|
||||
this.inner = verification.qrcode
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
internal class OlmMachine(
|
||||
user_id: String,
|
||||
device_id: String,
|
||||
@ -523,24 +664,16 @@ internal class OlmMachine(
|
||||
runBlocking { inner.discardRoomKey(roomId) }
|
||||
}
|
||||
|
||||
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
||||
return this.inner.getVerificationRequests(userId).map {
|
||||
VerificationRequest(this.inner, it)
|
||||
}
|
||||
fun getVerificationRequests(userId: String): List<uniffi.olm.VerificationRequest> {
|
||||
return this.inner.getVerificationRequests(userId)
|
||||
}
|
||||
|
||||
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
||||
val request = this.inner.getVerificationRequest(userId, flowId)
|
||||
|
||||
return if (request == null) {
|
||||
null
|
||||
} else {
|
||||
VerificationRequest(this.inner, request)
|
||||
}
|
||||
return this.inner.getVerificationRequest(userId, flowId)
|
||||
}
|
||||
|
||||
/** Get an active verification */
|
||||
fun getVerification(userId: String, flowId: String): Sas? {
|
||||
fun getVerification(userId: String, flowId: String): Verification? {
|
||||
return this.inner.getVerification(userId, flowId)
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import uniffi.olm.CryptoStoreErrorException
|
||||
import uniffi.olm.OlmMachine
|
||||
import uniffi.olm.OutgoingVerificationRequest
|
||||
import uniffi.olm.Sas
|
||||
import uniffi.olm.Verification
|
||||
|
||||
internal class SasVerification(
|
||||
private val machine: OlmMachine,
|
||||
@ -57,10 +58,11 @@ internal class SasVerification(
|
||||
}
|
||||
|
||||
private fun refreshData() {
|
||||
val sas = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)
|
||||
|
||||
if (sas != null) {
|
||||
this.inner = sas
|
||||
when (val verification = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)) {
|
||||
is Verification.SasV1 -> {
|
||||
this.inner = verification.sas
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificatio
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoReady
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest
|
||||
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.safeValueOf
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW
|
||||
@ -34,7 +35,9 @@ import uniffi.olm.VerificationRequest
|
||||
|
||||
internal class VerificationRequest(
|
||||
private val machine: OlmMachine,
|
||||
private var inner: VerificationRequest
|
||||
private var inner: VerificationRequest,
|
||||
private val sender: RequestSender,
|
||||
private val listeners: ArrayList<VerificationService.Listener>,
|
||||
) {
|
||||
private fun refreshData() {
|
||||
val request = this.machine.getVerificationRequest(this.inner.otherUserId, this.inner.flowId)
|
||||
@ -46,6 +49,21 @@ internal class VerificationRequest(
|
||||
return
|
||||
}
|
||||
|
||||
internal fun startQrVerification(): QrCodeVerification? {
|
||||
val qrcode = this.machine.startQrVerification(this.inner.otherUserId, this.inner.flowId)
|
||||
|
||||
return if (qrcode != null) {
|
||||
QrCodeVerification(
|
||||
this.machine,
|
||||
qrcode,
|
||||
this.sender,
|
||||
this.listeners,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun acceptWithMethods(methods: List<VerificationMethod>): OutgoingVerificationRequest? {
|
||||
val stringMethods: MutableList<String> =
|
||||
methods
|
||||
|
@ -29,14 +29,17 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.internal.crypto.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.QrCodeVerification
|
||||
import org.matrix.android.sdk.internal.crypto.RequestSender
|
||||
import org.matrix.android.sdk.internal.crypto.SasVerification
|
||||
import org.matrix.android.sdk.internal.crypto.VerificationRequest
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationDone
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationKey
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationRequest
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import timber.log.Timber
|
||||
import uniffi.olm.OutgoingVerificationRequest
|
||||
import uniffi.olm.Verification
|
||||
|
||||
@SessionScope
|
||||
internal class RustVerificationService
|
||||
@ -183,13 +186,16 @@ constructor(
|
||||
tid: String,
|
||||
): VerificationTransaction? {
|
||||
val verification = this.olmMachine.getVerification(otherUserId, tid) ?: return null
|
||||
return SasVerification(this.olmMachine.inner(), verification, this.requestSender, this.listeners)
|
||||
return when (verification) {
|
||||
is Verification.QrCodeV1 -> QrCodeVerification(this.olmMachine.inner(), verification.qrcode, this.requestSender, this.listeners)
|
||||
is Verification.SasV1 -> SasVerification(this.olmMachine.inner(), verification.sas, this.requestSender, this.listeners)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getExistingVerificationRequests(
|
||||
otherUserId: String
|
||||
): List<PendingVerificationRequest> {
|
||||
return this.olmMachine.getVerificationRequests(otherUserId).map {
|
||||
return this.getVerificationRequests(otherUserId).map {
|
||||
it.toPendingVerificationRequest()
|
||||
}
|
||||
}
|
||||
@ -199,7 +205,7 @@ constructor(
|
||||
tid: String?
|
||||
): PendingVerificationRequest? {
|
||||
return if (tid != null) {
|
||||
olmMachine.getVerificationRequest(otherUserId, tid)?.toPendingVerificationRequest()
|
||||
this.getVerificationRequest(otherUserId, tid)?.toPendingVerificationRequest()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -221,7 +227,7 @@ constructor(
|
||||
// should check if already one (and cancel it)
|
||||
return if (method == VerificationMethod.SAS) {
|
||||
val flowId = transactionId ?: return null
|
||||
val request = this.olmMachine.getVerificationRequest(otherUserId, flowId)
|
||||
val request = this.getVerificationRequest(otherUserId, flowId)
|
||||
runBlocking {
|
||||
val response = request?.startSasVerification()
|
||||
if (response != null) {
|
||||
@ -297,12 +303,38 @@ constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getVerificationRequest(otherUserId: String, transactionId: String): VerificationRequest? {
|
||||
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
|
||||
|
||||
return if (request != null) {
|
||||
VerificationRequest(
|
||||
this.olmMachine.inner(),
|
||||
request,
|
||||
requestSender,
|
||||
listeners,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
||||
return this.olmMachine.getVerificationRequests(userId).map {
|
||||
VerificationRequest(
|
||||
this.olmMachine.inner(),
|
||||
it,
|
||||
this.requestSender,
|
||||
this.listeners,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun readyPendingVerification(
|
||||
methods: List<VerificationMethod>,
|
||||
otherUserId: String,
|
||||
transactionId: String
|
||||
): Boolean {
|
||||
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
|
||||
val request = this.getVerificationRequest(otherUserId, transactionId)
|
||||
|
||||
return if (request != null) {
|
||||
val outgoingRequest = request.acceptWithMethods(methods)
|
||||
@ -310,6 +342,10 @@ constructor(
|
||||
if (outgoingRequest != null) {
|
||||
runBlocking { sendRequest(outgoingRequest) }
|
||||
dispatchRequestUpdated(request.toPendingVerificationRequest())
|
||||
val qrcode = request.startQrVerification()
|
||||
if (qrcode != null) {
|
||||
dispatchTxAdded(qrcode)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
Loading…
Reference in New Issue
Block a user