mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-01-01 13:58:32 +03:00
crypto: Add proper scopes to our verification methods
This commit is contained in:
parent
2097f4e6c2
commit
93f36db43c
4 changed files with 117 additions and 131 deletions
|
@ -156,7 +156,7 @@ internal class QrCodeVerification(
|
||||||
* This confirms that the other side has scanned our QR code.
|
* This confirms that the other side has scanned our QR code.
|
||||||
*/
|
*/
|
||||||
@Throws(CryptoStoreErrorException::class)
|
@Throws(CryptoStoreErrorException::class)
|
||||||
suspend fun confirm() {
|
private suspend fun confirm() {
|
||||||
val request = withContext(Dispatchers.IO)
|
val request = withContext(Dispatchers.IO)
|
||||||
{
|
{
|
||||||
machine.confirmVerification(request.otherUser(), request.flowId())
|
machine.confirmVerification(request.otherUser(), request.flowId())
|
||||||
|
@ -167,14 +167,6 @@ internal class QrCodeVerification(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send out a verification request in a blocking manner*/
|
|
||||||
private fun sendRequest(request: OutgoingVerificationRequest) {
|
|
||||||
runBlocking { sender.sendVerificationRequest(request) }
|
|
||||||
|
|
||||||
refreshData()
|
|
||||||
dispatchTxUpdated()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cancelHelper(code: CancelCode) {
|
private fun cancelHelper(code: CancelCode) {
|
||||||
val request = this.machine.cancelVerification(this.request.otherUser(), this.request.flowId(), code.value)
|
val request = this.machine.cancelVerification(this.request.otherUser(), this.request.flowId(), code.value)
|
||||||
|
|
||||||
|
@ -183,6 +175,14 @@ internal class QrCodeVerification(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Send out a verification request in a blocking manner*/
|
||||||
|
private fun sendRequest(request: OutgoingVerificationRequest) {
|
||||||
|
runBlocking { sender.sendVerificationRequest(request) }
|
||||||
|
|
||||||
|
refreshData()
|
||||||
|
dispatchTxUpdated()
|
||||||
|
}
|
||||||
|
|
||||||
/** Fetch fetch data from the Rust side for our verification flow */
|
/** Fetch fetch data from the Rust side for our verification flow */
|
||||||
private fun refreshData() {
|
private fun refreshData() {
|
||||||
when (val verification = this.machine.getVerification(this.request.otherUser(), this.request.flowId())) {
|
when (val verification = this.machine.getVerification(this.request.otherUser(), this.request.flowId())) {
|
||||||
|
|
|
@ -56,18 +56,6 @@ internal class SasVerification(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshData() {
|
|
||||||
when (val verification = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)) {
|
|
||||||
is Verification.SasV1 -> {
|
|
||||||
this.inner = verification.sas
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
override val isIncoming: Boolean
|
override val isIncoming: Boolean
|
||||||
get() = !this.inner.weStarted
|
get() = !this.inner.weStarted
|
||||||
|
|
||||||
|
@ -118,9 +106,8 @@ internal class SasVerification(
|
||||||
|
|
||||||
override fun supportsDecimal(): Boolean {
|
override fun supportsDecimal(): Boolean {
|
||||||
// This is ignored anyways, throw it away?
|
// This is ignored anyways, throw it away?
|
||||||
// The spec also mandates that devices support
|
// The spec also mandates that devices support at least decimal and
|
||||||
// at least decimal and the rust-sdk cancels if
|
// the rust-sdk cancels if devices don't support it
|
||||||
// devices don't support it
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,15 +117,26 @@ internal class SasVerification(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun userHasVerifiedShortCode() {
|
override fun userHasVerifiedShortCode() {
|
||||||
val request = runBlocking { confirm() } ?: return
|
runBlocking { confirm() }
|
||||||
sendRequest(request)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acceptVerification() {
|
override fun acceptVerification() {
|
||||||
runBlocking { accept() }
|
runBlocking { accept() }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun accept() {
|
override fun getDecimalCodeRepresentation(): String {
|
||||||
|
val decimals = this.machine.getDecimals(this.inner.otherUserId, this.inner.flowId)
|
||||||
|
|
||||||
|
return decimals?.joinToString(" ") ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getEmojiCodeRepresentation(): List<EmojiRepresentation> {
|
||||||
|
val emojiIndex = this.machine.getEmojiIndex(this.inner.otherUserId, this.inner.flowId)
|
||||||
|
|
||||||
|
return emojiIndex?.map { getEmojiForCode(it) } ?: listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal suspend fun accept() {
|
||||||
val request = this.machine.acceptSasVerification(this.inner.otherUserId, inner.flowId)
|
val request = this.machine.acceptSasVerification(this.inner.otherUserId, inner.flowId)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
|
@ -149,12 +147,16 @@ internal class SasVerification(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreErrorException::class)
|
@Throws(CryptoStoreErrorException::class)
|
||||||
suspend fun confirm(): OutgoingVerificationRequest? =
|
private suspend fun confirm() {
|
||||||
withContext(Dispatchers.IO) {
|
val request = withContext(Dispatchers.IO) {
|
||||||
machine.confirmVerification(inner.otherUserId, inner.flowId)
|
machine.confirmVerification(inner.otherUserId, inner.flowId)
|
||||||
}
|
}
|
||||||
|
if (request != null) {
|
||||||
|
this.sender.sendVerificationRequest(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun cancelHelper(code: CancelCode) {
|
private fun cancelHelper(code: CancelCode) {
|
||||||
val request = this.machine.cancelVerification(this.inner.otherUserId, inner.flowId, code.value)
|
val request = this.machine.cancelVerification(this.inner.otherUserId, inner.flowId, code.value)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
|
@ -162,24 +164,22 @@ internal class SasVerification(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEmojiCodeRepresentation(): List<EmojiRepresentation> {
|
private fun sendRequest(request: OutgoingVerificationRequest) {
|
||||||
val emojiIndex = this.machine.getEmojiIndex(this.inner.otherUserId, this.inner.flowId)
|
runBlocking { sender.sendVerificationRequest(request) }
|
||||||
|
|
||||||
return emojiIndex?.map { getEmojiForCode(it) } ?: listOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDecimalCodeRepresentation(): String {
|
|
||||||
val decimals = this.machine.getDecimals(this.inner.otherUserId, this.inner.flowId)
|
|
||||||
|
|
||||||
return decimals?.joinToString(" ") ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendRequest(request: OutgoingVerificationRequest) {
|
|
||||||
runBlocking {
|
|
||||||
sender.sendVerificationRequest(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshData()
|
refreshData()
|
||||||
dispatchTxUpdated()
|
dispatchTxUpdated()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun refreshData() {
|
||||||
|
when (val verification = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId)) {
|
||||||
|
is Verification.SasV1 -> {
|
||||||
|
this.inner = verification.sas
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE
|
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
|
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
|
import org.matrix.android.sdk.internal.crypto.model.rest.toValue
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uniffi.olm.OlmMachine
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.VerificationRequest
|
import uniffi.olm.VerificationRequest
|
||||||
|
@ -46,16 +47,6 @@ internal class VerificationRequest(
|
||||||
) {
|
) {
|
||||||
private val uiHandler = Handler(Looper.getMainLooper())
|
private val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
private fun refreshData() {
|
|
||||||
val request = this.machine.getVerificationRequest(this.inner.otherUserId, this.inner.flowId)
|
|
||||||
|
|
||||||
if (request != null) {
|
|
||||||
this.inner = request
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun dispatchRequestUpdated() {
|
internal fun dispatchRequestUpdated() {
|
||||||
uiHandler.post {
|
uiHandler.post {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
|
@ -68,42 +59,65 @@ internal class VerificationRequest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isCanceled(): Boolean {
|
internal fun flowId(): String {
|
||||||
refreshData()
|
|
||||||
return this.inner.isCancelled
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDone(): Boolean {
|
|
||||||
refreshData()
|
|
||||||
return this.inner.isDone
|
|
||||||
}
|
|
||||||
|
|
||||||
fun flowId(): String {
|
|
||||||
return this.inner.flowId
|
return this.inner.flowId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun otherUser(): String {
|
internal fun otherUser(): String {
|
||||||
return this.inner.otherUserId
|
return this.inner.otherUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun otherDeviceId(): String? {
|
internal fun otherDeviceId(): String? {
|
||||||
refreshData()
|
refreshData()
|
||||||
return this.inner.otherDeviceId
|
return this.inner.otherDeviceId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun weStarted(): Boolean {
|
internal fun weStarted(): Boolean {
|
||||||
return this.inner.weStarted
|
return this.inner.weStarted
|
||||||
}
|
}
|
||||||
|
|
||||||
fun roomId(): String? {
|
internal fun roomId(): String? {
|
||||||
return this.inner.roomId
|
return this.inner.roomId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isReady(): Boolean {
|
internal fun isReady(): Boolean {
|
||||||
refreshData()
|
refreshData()
|
||||||
return this.inner.isReady
|
return this.inner.isReady
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun canScanQrCodes(): Boolean {
|
||||||
|
refreshData()
|
||||||
|
return this.inner.ourMethods?.contains(VERIFICATION_METHOD_QR_CODE_SCAN) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun acceptWithMethods(methods: List<VerificationMethod>) {
|
||||||
|
val stringMethods = prepareMethods(methods)
|
||||||
|
|
||||||
|
val request = this.machine.acceptVerificationRequest(
|
||||||
|
this.inner.otherUserId,
|
||||||
|
this.inner.flowId,
|
||||||
|
stringMethods
|
||||||
|
)
|
||||||
|
|
||||||
|
if (request != null) {
|
||||||
|
this.sender.sendVerificationRequest(request)
|
||||||
|
this.dispatchRequestUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal suspend fun startSasVerification(): SasVerification? {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
val result = machine.startSasVerification(inner.otherUserId, inner.flowId)
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
sender.sendVerificationRequest(result.request)
|
||||||
|
SasVerification(machine, result.sas, sender, listeners)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal suspend fun scanQrCode(data: String): QrCodeVerification? {
|
internal suspend fun scanQrCode(data: String): QrCodeVerification? {
|
||||||
// TODO again, what's the deal with ISO_8859_1?
|
// TODO again, what's the deal with ISO_8859_1?
|
||||||
val byteArray = data.toByteArray(Charsets.ISO_8859_1)
|
val byteArray = data.toByteArray(Charsets.ISO_8859_1)
|
||||||
|
@ -130,18 +144,11 @@ internal class VerificationRequest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun acceptWithMethods(methods: List<VerificationMethod>) {
|
internal suspend fun cancel() {
|
||||||
val stringMethods: MutableList<String> = methods.map { it.toValue() }.toMutableList()
|
val request = this.machine.cancelVerification(
|
||||||
|
|
||||||
if (stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SHOW) ||
|
|
||||||
stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SCAN)) {
|
|
||||||
stringMethods.add(VERIFICATION_METHOD_RECIPROCATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val request = this.machine.acceptVerificationRequest(
|
|
||||||
this.inner.otherUserId,
|
this.inner.otherUserId,
|
||||||
this.inner.flowId,
|
this.inner.flowId,
|
||||||
stringMethods
|
CancelCode.User.value
|
||||||
)
|
)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
|
@ -150,35 +157,15 @@ internal class VerificationRequest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun cancel() {
|
private fun refreshData() {
|
||||||
val request = this.machine.cancelVerification(this.inner.otherUserId, this.inner.flowId, CancelCode.User.value)
|
val request = this.machine.getVerificationRequest(this.inner.otherUserId, this.inner.flowId)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
this.sender.sendVerificationRequest(request)
|
this.inner = request
|
||||||
this.dispatchRequestUpdated()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun canScanQrCodes(): Boolean {
|
internal fun toPendingVerificationRequest(): PendingVerificationRequest {
|
||||||
refreshData()
|
|
||||||
return this.inner.ourMethods?.contains(VERIFICATION_METHOD_QR_CODE_SCAN) ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun startSasVerification(): SasVerification? {
|
|
||||||
refreshData()
|
|
||||||
|
|
||||||
return withContext(Dispatchers.IO) {
|
|
||||||
val result = machine.startSasVerification(inner.otherUserId, inner.flowId)
|
|
||||||
if (result != null) {
|
|
||||||
sender.sendVerificationRequest(result.request)
|
|
||||||
SasVerification(machine, result.sas, sender, listeners)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toPendingVerificationRequest(): PendingVerificationRequest {
|
|
||||||
refreshData()
|
refreshData()
|
||||||
val cancelInfo = this.inner.cancelInfo
|
val cancelInfo = this.inner.cancelInfo
|
||||||
val cancelCode =
|
val cancelCode =
|
||||||
|
|
|
@ -46,7 +46,7 @@ import timber.log.Timber
|
||||||
import uniffi.olm.Verification
|
import uniffi.olm.Verification
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class ToDeviceVerificationEvent(
|
internal data class ToDeviceVerificationEvent(
|
||||||
@Json(name = "sender") val sender: String?,
|
@Json(name = "sender") val sender: String?,
|
||||||
@Json(name = "transaction_id") val transactionId: String,
|
@Json(name = "transaction_id") val transactionId: String,
|
||||||
)
|
)
|
||||||
|
@ -61,6 +61,17 @@ private fun getFlowId(event: Event): String? {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun prepareMethods(methods: List<VerificationMethod>): List<String> {
|
||||||
|
val stringMethods: MutableList<String> = methods.map { it.toValue() }.toMutableList()
|
||||||
|
|
||||||
|
if (stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SHOW) ||
|
||||||
|
stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SCAN)) {
|
||||||
|
stringMethods.add(VERIFICATION_METHOD_RECIPROCATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringMethods
|
||||||
|
}
|
||||||
|
|
||||||
internal class RustVerificationService(
|
internal class RustVerificationService(
|
||||||
private val olmMachine: OlmMachine,
|
private val olmMachine: OlmMachine,
|
||||||
private val requestSender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
|
@ -117,7 +128,7 @@ internal class RustVerificationService(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun onEvent(event: Event) = when (event.getClearType()) {
|
internal suspend fun onEvent(event: Event) = when (event.getClearType()) {
|
||||||
MessageType.MSGTYPE_VERIFICATION_REQUEST -> onRequest(event)
|
MessageType.MSGTYPE_VERIFICATION_REQUEST -> onRequest(event)
|
||||||
EventType.KEY_VERIFICATION_START -> onStart(event)
|
EventType.KEY_VERIFICATION_START -> onStart(event)
|
||||||
EventType.KEY_VERIFICATION_READY,
|
EventType.KEY_VERIFICATION_READY,
|
||||||
|
@ -148,8 +159,8 @@ internal class RustVerificationService(
|
||||||
|
|
||||||
if (request != null && request.isReady()) {
|
if (request != null && request.isReady()) {
|
||||||
// If this is a SAS verification originating from a `m.key.verification.request`
|
// If this is a SAS verification originating from a `m.key.verification.request`
|
||||||
// event we auto-accept here considering that we either initiated the request or
|
// event, we auto-accept here considering that we either initiated the request or
|
||||||
// accepted the request, otherwise it's a QR code verification, just dispatch an update.
|
// accepted the request. If it's a QR code verification, just dispatch an update.
|
||||||
if (verification is SasVerification) {
|
if (verification is SasVerification) {
|
||||||
// Accept dispatches an update, no need to do it twice.
|
// Accept dispatches an update, no need to do it twice.
|
||||||
Timber.d("## Verification: Auto accepting SAS verification with $sender")
|
Timber.d("## Verification: Auto accepting SAS verification with $sender")
|
||||||
|
@ -296,12 +307,7 @@ internal class RustVerificationService(
|
||||||
otherUserId: String,
|
otherUserId: String,
|
||||||
otherDevices: List<String>?
|
otherDevices: List<String>?
|
||||||
): PendingVerificationRequest {
|
): PendingVerificationRequest {
|
||||||
|
val stringMethods = prepareMethods(methods)
|
||||||
val stringMethods: MutableList<String> = methods.map { it.toValue() }.toMutableList()
|
|
||||||
if (stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SHOW) ||
|
|
||||||
stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SCAN)) {
|
|
||||||
stringMethods.add(VERIFICATION_METHOD_RECIPROCATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = this.olmMachine.inner().requestSelfVerification(stringMethods)
|
val result = this.olmMachine.inner().requestSelfVerification(stringMethods)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
@ -318,13 +324,7 @@ internal class RustVerificationService(
|
||||||
localId: String?
|
localId: String?
|
||||||
): PendingVerificationRequest {
|
): PendingVerificationRequest {
|
||||||
Timber.i("## SAS Requesting verification to user: $otherUserId in room $roomId")
|
Timber.i("## SAS Requesting verification to user: $otherUserId in room $roomId")
|
||||||
val stringMethods: MutableList<String> = methods.map { it.toValue() }.toMutableList()
|
val stringMethods = prepareMethods(methods)
|
||||||
|
|
||||||
if (stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SHOW) ||
|
|
||||||
stringMethods.contains(VERIFICATION_METHOD_QR_CODE_SCAN)) {
|
|
||||||
stringMethods.add(VERIFICATION_METHOD_RECIPROCATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val content = this.olmMachine.inner().verificationRequestContent(otherUserId, stringMethods)!!
|
val content = this.olmMachine.inner().verificationRequestContent(otherUserId, stringMethods)!!
|
||||||
|
|
||||||
val eventID = runBlocking {
|
val eventID = runBlocking {
|
||||||
|
@ -376,7 +376,6 @@ internal class RustVerificationService(
|
||||||
otherDeviceId: String,
|
otherDeviceId: String,
|
||||||
transactionId: String?
|
transactionId: String?
|
||||||
): String? {
|
): String? {
|
||||||
// should check if already one (and cancel it)
|
|
||||||
return if (method == VerificationMethod.SAS) {
|
return if (method == VerificationMethod.SAS) {
|
||||||
if (transactionId != null) {
|
if (transactionId != null) {
|
||||||
val request = this.getVerificationRequest(otherUserId, transactionId)
|
val request = this.getVerificationRequest(otherUserId, transactionId)
|
||||||
|
|
Loading…
Reference in a new issue