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
|
package org.matrix.android.sdk.internal.crypto
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -26,10 +28,16 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
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.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.Content
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
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.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.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||||
@ -45,11 +53,14 @@ import uniffi.olm.Device
|
|||||||
import uniffi.olm.DeviceLists
|
import uniffi.olm.DeviceLists
|
||||||
import uniffi.olm.KeyRequestPair
|
import uniffi.olm.KeyRequestPair
|
||||||
import uniffi.olm.Logger
|
import uniffi.olm.Logger
|
||||||
|
import uniffi.olm.OutgoingVerificationRequest
|
||||||
|
import uniffi.olm.QrCode
|
||||||
import uniffi.olm.OlmMachine as InnerMachine
|
import uniffi.olm.OlmMachine as InnerMachine
|
||||||
import uniffi.olm.ProgressListener as RustProgressListener
|
import uniffi.olm.ProgressListener as RustProgressListener
|
||||||
import uniffi.olm.Request
|
import uniffi.olm.Request
|
||||||
import uniffi.olm.RequestType
|
import uniffi.olm.RequestType
|
||||||
import uniffi.olm.Sas
|
import uniffi.olm.Verification
|
||||||
|
import uniffi.olm.VerificationRequest
|
||||||
import uniffi.olm.setLogger
|
import uniffi.olm.setLogger
|
||||||
|
|
||||||
class CryptoLogger : Logger {
|
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(
|
internal class OlmMachine(
|
||||||
user_id: String,
|
user_id: String,
|
||||||
device_id: String,
|
device_id: String,
|
||||||
@ -523,24 +664,16 @@ internal class OlmMachine(
|
|||||||
runBlocking { inner.discardRoomKey(roomId) }
|
runBlocking { inner.discardRoomKey(roomId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
fun getVerificationRequests(userId: String): List<uniffi.olm.VerificationRequest> {
|
||||||
return this.inner.getVerificationRequests(userId).map {
|
return this.inner.getVerificationRequests(userId)
|
||||||
VerificationRequest(this.inner, it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
||||||
val request = this.inner.getVerificationRequest(userId, flowId)
|
return this.inner.getVerificationRequest(userId, flowId)
|
||||||
|
|
||||||
return if (request == null) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
VerificationRequest(this.inner, request)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get an active verification */
|
/** Get an active verification */
|
||||||
fun getVerification(userId: String, flowId: String): Sas? {
|
fun getVerification(userId: String, flowId: String): Verification? {
|
||||||
return this.inner.getVerification(userId, flowId)
|
return this.inner.getVerification(userId, flowId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import uniffi.olm.CryptoStoreErrorException
|
|||||||
import uniffi.olm.OlmMachine
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.OutgoingVerificationRequest
|
import uniffi.olm.OutgoingVerificationRequest
|
||||||
import uniffi.olm.Sas
|
import uniffi.olm.Sas
|
||||||
|
import uniffi.olm.Verification
|
||||||
|
|
||||||
internal class SasVerification(
|
internal class SasVerification(
|
||||||
private val machine: OlmMachine,
|
private val machine: OlmMachine,
|
||||||
@ -57,10 +58,11 @@ internal class SasVerification(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshData() {
|
private fun refreshData() {
|
||||||
val sas = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)
|
when (val verification = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)) {
|
||||||
|
is Verification.SasV1 -> {
|
||||||
if (sas != null) {
|
this.inner = verification.sas
|
||||||
this.inner = sas
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
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.ValidVerificationInfoReady
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest
|
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.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.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_SCAN
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW
|
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(
|
internal class VerificationRequest(
|
||||||
private val machine: OlmMachine,
|
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() {
|
private fun refreshData() {
|
||||||
val request = this.machine.getVerificationRequest(this.inner.otherUserId, this.inner.flowId)
|
val request = this.machine.getVerificationRequest(this.inner.otherUserId, this.inner.flowId)
|
||||||
@ -46,6 +49,21 @@ internal class VerificationRequest(
|
|||||||
return
|
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? {
|
fun acceptWithMethods(methods: List<VerificationMethod>): OutgoingVerificationRequest? {
|
||||||
val stringMethods: MutableList<String> =
|
val stringMethods: MutableList<String> =
|
||||||
methods
|
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.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
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.OlmMachine
|
||||||
|
import org.matrix.android.sdk.internal.crypto.QrCodeVerification
|
||||||
import org.matrix.android.sdk.internal.crypto.RequestSender
|
import org.matrix.android.sdk.internal.crypto.RequestSender
|
||||||
import org.matrix.android.sdk.internal.crypto.SasVerification
|
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.KeyVerificationDone
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationKey
|
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.crypto.model.rest.KeyVerificationRequest
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uniffi.olm.OutgoingVerificationRequest
|
import uniffi.olm.OutgoingVerificationRequest
|
||||||
|
import uniffi.olm.Verification
|
||||||
|
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal class RustVerificationService
|
internal class RustVerificationService
|
||||||
@ -183,13 +186,16 @@ constructor(
|
|||||||
tid: String,
|
tid: String,
|
||||||
): VerificationTransaction? {
|
): VerificationTransaction? {
|
||||||
val verification = this.olmMachine.getVerification(otherUserId, tid) ?: return null
|
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(
|
override fun getExistingVerificationRequests(
|
||||||
otherUserId: String
|
otherUserId: String
|
||||||
): List<PendingVerificationRequest> {
|
): List<PendingVerificationRequest> {
|
||||||
return this.olmMachine.getVerificationRequests(otherUserId).map {
|
return this.getVerificationRequests(otherUserId).map {
|
||||||
it.toPendingVerificationRequest()
|
it.toPendingVerificationRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +205,7 @@ constructor(
|
|||||||
tid: String?
|
tid: String?
|
||||||
): PendingVerificationRequest? {
|
): PendingVerificationRequest? {
|
||||||
return if (tid != null) {
|
return if (tid != null) {
|
||||||
olmMachine.getVerificationRequest(otherUserId, tid)?.toPendingVerificationRequest()
|
this.getVerificationRequest(otherUserId, tid)?.toPendingVerificationRequest()
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@ -221,7 +227,7 @@ constructor(
|
|||||||
// should check if already one (and cancel it)
|
// should check if already one (and cancel it)
|
||||||
return if (method == VerificationMethod.SAS) {
|
return if (method == VerificationMethod.SAS) {
|
||||||
val flowId = transactionId ?: return null
|
val flowId = transactionId ?: return null
|
||||||
val request = this.olmMachine.getVerificationRequest(otherUserId, flowId)
|
val request = this.getVerificationRequest(otherUserId, flowId)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val response = request?.startSasVerification()
|
val response = request?.startSasVerification()
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
@ -297,12 +303,38 @@ constructor(
|
|||||||
return true
|
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(
|
override fun readyPendingVerification(
|
||||||
methods: List<VerificationMethod>,
|
methods: List<VerificationMethod>,
|
||||||
otherUserId: String,
|
otherUserId: String,
|
||||||
transactionId: String
|
transactionId: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
|
val request = this.getVerificationRequest(otherUserId, transactionId)
|
||||||
|
|
||||||
return if (request != null) {
|
return if (request != null) {
|
||||||
val outgoingRequest = request.acceptWithMethods(methods)
|
val outgoingRequest = request.acceptWithMethods(methods)
|
||||||
@ -310,6 +342,10 @@ constructor(
|
|||||||
if (outgoingRequest != null) {
|
if (outgoingRequest != null) {
|
||||||
runBlocking { sendRequest(outgoingRequest) }
|
runBlocking { sendRequest(outgoingRequest) }
|
||||||
dispatchRequestUpdated(request.toPendingVerificationRequest())
|
dispatchRequestUpdated(request.toPendingVerificationRequest())
|
||||||
|
val qrcode = request.startQrVerification()
|
||||||
|
if (qrcode != null) {
|
||||||
|
dispatchTxAdded(qrcode)
|
||||||
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
Loading…
Reference in New Issue
Block a user