mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Merge pull request #297 from vector-im/feature/crypto_stabilization
Safely remove all usage of `!![`
This commit is contained in:
commit
f2a52f0253
@ -78,6 +78,8 @@ class MXCryptoError(var code: String,
|
||||
|
||||
companion object {
|
||||
|
||||
// TODO Create sealed class
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
*/
|
||||
@ -88,7 +90,10 @@ class MXCryptoError(var code: String,
|
||||
const val UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE = "UNKNOWN_INBOUND_SESSION_ID"
|
||||
const val INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE = "INBOUND_SESSION_MISMATCH_ROOM_ID"
|
||||
const val MISSING_FIELDS_ERROR_CODE = "MISSING_FIELDS"
|
||||
const val BAD_EVENT_FORMAT_ERROR_CODE = "BAD_EVENT_FORMAT_ERROR_CODE"
|
||||
const val MISSING_SENDER_KEY_ERROR_CODE = "MISSING_SENDER_KEY_ERROR_CODE"
|
||||
const val MISSING_CIPHER_TEXT_ERROR_CODE = "MISSING_CIPHER_TEXT"
|
||||
const val BAD_DECRYPTED_FORMAT_ERROR_CODE = "BAD_DECRYPTED_FORMAT_ERROR_CODE"
|
||||
const val NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE = "NOT_INCLUDE_IN_RECIPIENTS"
|
||||
const val BAD_RECIPIENT_ERROR_CODE = "BAD_RECIPIENT"
|
||||
const val BAD_RECIPIENT_KEY_ERROR_CODE = "BAD_RECIPIENT_KEY"
|
||||
@ -118,7 +123,10 @@ class MXCryptoError(var code: String,
|
||||
const val UNKNOWN_INBOUND_SESSION_ID_REASON = "Unknown inbound session id"
|
||||
const val INBOUND_SESSION_MISMATCH_ROOM_ID_REASON = "Mismatched room_id for inbound group session (expected %1\$s, was %2\$s)"
|
||||
const val MISSING_FIELDS_REASON = "Missing fields in input"
|
||||
const val BAD_EVENT_FORMAT_TEXT_REASON = "Bad event format"
|
||||
const val MISSING_SENDER_KEY_TEXT_REASON = "Missing senderKey"
|
||||
const val MISSING_CIPHER_TEXT_REASON = "Missing ciphertext"
|
||||
const val BAD_DECRYPTED_FORMAT_TEXT_REASON = "Bad decrypted event format"
|
||||
const val NOT_INCLUDED_IN_RECIPIENT_REASON = "Not included in recipients"
|
||||
const val BAD_RECIPIENT_REASON = "Message was intended for %1\$s"
|
||||
const val BAD_RECIPIENT_KEY_REASON = "Message not intended for this device"
|
||||
|
@ -210,13 +210,7 @@ class CreateRoomParams {
|
||||
* @return the first invited user id
|
||||
*/
|
||||
fun getFirstInvitedUserId(): String? {
|
||||
if (0 != getInviteCount()) {
|
||||
return invitedUserIds!![0]
|
||||
}
|
||||
|
||||
return if (0 != getInvite3PidCount()) {
|
||||
invite3pids!![0].address
|
||||
} else null
|
||||
return invitedUserIds?.firstOrNull() ?: invite3pids?.firstOrNull()?.address
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,11 +21,11 @@ import android.text.TextUtils
|
||||
import arrow.core.Try
|
||||
import im.vector.matrix.android.api.MatrixPatterns
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.internal.extensions.onError
|
||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||
import im.vector.matrix.android.internal.crypto.tasks.DownloadKeysForUsersTask
|
||||
import im.vector.matrix.android.internal.extensions.onError
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
||||
import timber.log.Timber
|
||||
@ -380,14 +380,14 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM
|
||||
}
|
||||
|
||||
val signKeyId = "ed25519:" + deviceKeys.deviceId
|
||||
val signKey = deviceKeys.keys!![signKeyId]
|
||||
val signKey = deviceKeys.keys?.get(signKeyId)
|
||||
|
||||
if (null == signKey) {
|
||||
Timber.e("## validateDeviceKeys() : Device " + userId + ":" + deviceKeys.deviceId + " has no ed25519 key")
|
||||
return false
|
||||
}
|
||||
|
||||
val signatureMap = deviceKeys.signatures!![userId]
|
||||
val signatureMap = deviceKeys.signatures?.get(userId)
|
||||
|
||||
if (null == signatureMap) {
|
||||
Timber.e("## validateDeviceKeys() : Device " + userId + ":" + deviceKeys.deviceId + " has no map for " + userId)
|
||||
@ -413,7 +413,7 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM
|
||||
|
||||
if (!isVerified) {
|
||||
Timber.e("## validateDeviceKeys() : Unable to verify signature on device " + userId + ":"
|
||||
+ deviceKeys.deviceId + " with error " + errorMessage)
|
||||
+ deviceKeys.deviceId + " with error " + errorMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
@ -424,8 +424,8 @@ internal class DeviceListManager @Inject constructor(private val cryptoStore: IM
|
||||
//
|
||||
// Should we warn the user about it somehow?
|
||||
Timber.e("## validateDeviceKeys() : WARNING:Ed25519 key for device " + userId + ":"
|
||||
+ deviceKeys.deviceId + " has changed : "
|
||||
+ previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey)
|
||||
+ deviceKeys.deviceId + " has changed : "
|
||||
+ previouslyStoredDeviceKeys.fingerprint() + " -> " + signKey)
|
||||
|
||||
Timber.e("## validateDeviceKeys() : $previouslyStoredDeviceKeys -> $deviceKeys")
|
||||
Timber.e("## validateDeviceKeys() : " + previouslyStoredDeviceKeys.keys + " -> " + deviceKeys.keys)
|
||||
|
@ -667,7 +667,7 @@ internal class MXOlmDevice @Inject constructor(
|
||||
|
||||
val messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex
|
||||
|
||||
if (null != inboundGroupSessionMessageIndexes[timeline]!![messageIndexKey]) {
|
||||
if (inboundGroupSessionMessageIndexes[timeline]?.get(messageIndexKey) != null) {
|
||||
val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
|
||||
Timber.e("## decryptGroupMessage() : $reason")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE,
|
||||
|
@ -150,7 +150,7 @@ internal class OneTimeKeysUploader @Inject constructor(
|
||||
val oneTimeKeys = olmDevice.getOneTimeKeys()
|
||||
val oneTimeJson = HashMap<String, Any>()
|
||||
|
||||
val curve25519Map = oneTimeKeys!![OlmAccount.JSON_KEY_ONE_TIME_KEY]
|
||||
val curve25519Map = oneTimeKeys?.get(OlmAccount.JSON_KEY_ONE_TIME_KEY)
|
||||
|
||||
if (null != curve25519Map) {
|
||||
for (key_id in curve25519Map.keys) {
|
||||
|
@ -179,13 +179,13 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||
pendingEvents[pendingEventsKey] = HashMap()
|
||||
}
|
||||
|
||||
if (!pendingEvents[pendingEventsKey]!!.containsKey(timelineId)) {
|
||||
pendingEvents[pendingEventsKey]!![timelineId] = ArrayList()
|
||||
if (pendingEvents[pendingEventsKey]?.containsKey(timelineId) == false) {
|
||||
pendingEvents[pendingEventsKey]?.put(timelineId, ArrayList())
|
||||
}
|
||||
|
||||
if (pendingEvents[pendingEventsKey]!![timelineId]!!.indexOf(event) < 0) {
|
||||
if (pendingEvents[pendingEventsKey]?.get(timelineId)?.contains(event) == false) {
|
||||
Timber.v("## addEventToPendingList() : add Event " + event.eventId + " in room id " + event.roomId)
|
||||
pendingEvents[pendingEventsKey]!![timelineId]!!.add(event)
|
||||
pendingEvents[pendingEventsKey]?.get(timelineId)?.add(event)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
package im.vector.matrix.android.internal.crypto.algorithms.olm
|
||||
|
||||
import android.text.TextUtils
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
@ -44,36 +43,47 @@ internal class MXOlmDecryption(
|
||||
|
||||
@Throws(MXDecryptionException::class)
|
||||
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
|
||||
val olmEventContent = event.content.toModel<OlmEventContent>()!!
|
||||
val olmEventContent = event.content.toModel<OlmEventContent>() ?: run {
|
||||
Timber.e("## decryptEvent() : bad event format")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_EVENT_FORMAT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_EVENT_FORMAT_TEXT_REASON))
|
||||
}
|
||||
|
||||
if (null == olmEventContent.ciphertext) {
|
||||
val cipherText = olmEventContent.ciphertext ?: run {
|
||||
Timber.e("## decryptEvent() : missing cipher text")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_CIPHER_TEXT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON))
|
||||
}
|
||||
|
||||
if (!olmEventContent.ciphertext!!.containsKey(olmDevice.deviceCurve25519Key)) {
|
||||
Timber.e("## decryptEvent() : our device " + olmDevice.deviceCurve25519Key
|
||||
+ " is not included in recipients. Event")
|
||||
val senderKey = olmEventContent.senderKey ?: run {
|
||||
Timber.e("## decryptEvent() : missing sender key")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_SENDER_KEY_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_SENDER_KEY_TEXT_REASON))
|
||||
}
|
||||
|
||||
val messageAny = cipherText[olmDevice.deviceCurve25519Key] ?: run {
|
||||
Timber.e("## decryptEvent() : our device ${olmDevice.deviceCurve25519Key} is not included in recipients")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON))
|
||||
}
|
||||
|
||||
// The message for myUser
|
||||
val message = olmEventContent.ciphertext!![olmDevice.deviceCurve25519Key] as JsonDict
|
||||
val decryptedPayload = decryptMessage(message, olmEventContent.senderKey!!)
|
||||
val message = messageAny as JsonDict
|
||||
|
||||
val decryptedPayload = decryptMessage(message, senderKey)
|
||||
|
||||
if (decryptedPayload == null) {
|
||||
Timber.e("## decryptEvent() Failed to decrypt Olm event (id= " + event.eventId + " ) from " + olmEventContent.senderKey)
|
||||
Timber.e("## decryptEvent() Failed to decrypt Olm event (id= ${event.eventId} from $senderKey")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_ENCRYPTED_MESSAGE_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON))
|
||||
}
|
||||
val payloadString = convertFromUTF8(decryptedPayload)
|
||||
if (payloadString == null) {
|
||||
Timber.e("## decryptEvent() Failed to decrypt Olm event (id= " + event.eventId + " ) from " + olmEventContent.senderKey)
|
||||
Timber.e("## decryptEvent() Failed to decrypt Olm event (id= ${event.eventId} from $senderKey")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_ENCRYPTED_MESSAGE_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON))
|
||||
}
|
||||
|
||||
val adapter = MoshiProvider.providesMoshi().adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
val payload = adapter.fromJson(payloadString)
|
||||
|
||||
@ -83,59 +93,58 @@ internal class MXOlmDecryption(
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON))
|
||||
}
|
||||
|
||||
val olmPayloadContent = OlmPayloadContent.fromJsonString(payloadString)
|
||||
val olmPayloadContent = OlmPayloadContent.fromJsonString(payloadString) ?: run {
|
||||
Timber.e("## decryptEvent() : bad olmPayloadContent format")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_DECRYPTED_FORMAT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON))
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(olmPayloadContent.recipient)) {
|
||||
if (olmPayloadContent.recipient.isNullOrBlank()) {
|
||||
val reason = String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient")
|
||||
Timber.e("## decryptEvent() : $reason")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_PROPERTY_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, reason))
|
||||
}
|
||||
|
||||
if (!TextUtils.equals(olmPayloadContent.recipient, credentials.userId)) {
|
||||
Timber.e("## decryptEvent() : Event " + event.eventId + ": Intended recipient " + olmPayloadContent.recipient
|
||||
+ " does not match our id " + credentials.userId)
|
||||
if (olmPayloadContent.recipient != credentials.userId) {
|
||||
Timber.e("## decryptEvent() : Event ${event.eventId}: Intended recipient ${olmPayloadContent.recipient} does not match our id ${credentials.userId}")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_RECIPIENT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient)))
|
||||
}
|
||||
|
||||
if (null == olmPayloadContent.recipient_keys) {
|
||||
Timber.e("## decryptEvent() : Olm event (id=" + event.eventId
|
||||
+ ") contains no " + "'recipient_keys' property; cannot prevent unknown-key attack")
|
||||
val recipientKeys = olmPayloadContent.recipient_keys ?: run {
|
||||
Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'recipient_keys' property; cannot prevent unknown-key attack")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_PROPERTY_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "recipient_keys")))
|
||||
}
|
||||
|
||||
val ed25519 = olmPayloadContent.recipient_keys!!.get("ed25519")
|
||||
val ed25519 = recipientKeys["ed25519"]
|
||||
|
||||
if (!TextUtils.equals(ed25519, olmDevice.deviceEd25519Key)) {
|
||||
Timber.e("## decryptEvent() : Event " + event.eventId + ": Intended recipient ed25519 key " + ed25519 + " did not match ours")
|
||||
if (ed25519 != olmDevice.deviceEd25519Key) {
|
||||
Timber.e("## decryptEvent() : Event ${event.eventId}: Intended recipient ed25519 key $ed25519 did not match ours")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_RECIPIENT_KEY_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_RECIPIENT_KEY_REASON))
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(olmPayloadContent.sender)) {
|
||||
Timber.e("## decryptEvent() : Olm event (id=" + event.eventId
|
||||
+ ") contains no 'sender' property; cannot prevent unknown-key attack")
|
||||
if (olmPayloadContent.sender.isNullOrBlank()) {
|
||||
Timber.e("## decryptEvent() : Olm event (id=${event.eventId}) contains no 'sender' property; cannot prevent unknown-key attack")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.MISSING_PROPERTY_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, String.format(MXCryptoError.ERROR_MISSING_PROPERTY_REASON, "sender")))
|
||||
}
|
||||
|
||||
if (!TextUtils.equals(olmPayloadContent.sender, event.senderId)) {
|
||||
Timber.e("Event " + event.eventId + ": original sender " + olmPayloadContent.sender
|
||||
+ " does not match reported sender " + event.senderId)
|
||||
if (olmPayloadContent.sender != event.senderId) {
|
||||
Timber.e("Event ${event.eventId}: original sender ${olmPayloadContent.sender} does not match reported sender ${event.senderId}")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.FORWARDED_MESSAGE_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, String.format(MXCryptoError.FORWARDED_MESSAGE_REASON, olmPayloadContent.sender)))
|
||||
}
|
||||
|
||||
if (!TextUtils.equals(olmPayloadContent.room_id, event.roomId)) {
|
||||
Timber.e("## decryptEvent() : Event " + event.eventId + ": original room " + olmPayloadContent.room_id
|
||||
+ " does not match reported room " + event.roomId)
|
||||
if (olmPayloadContent.room_id != event.roomId) {
|
||||
Timber.e("## decryptEvent() : Event ${event.eventId}: original room ${olmPayloadContent.room_id} does not match reported room ${event.roomId}")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_ROOM_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, String.format(MXCryptoError.BAD_ROOM_REASON, olmPayloadContent.room_id)))
|
||||
}
|
||||
|
||||
if (null == olmPayloadContent.keys) {
|
||||
val keys = olmPayloadContent.keys ?: run {
|
||||
Timber.e("## decryptEvent failed : null keys")
|
||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON))
|
||||
@ -143,8 +152,8 @@ internal class MXOlmDecryption(
|
||||
|
||||
val result = MXEventDecryptionResult()
|
||||
result.clearEvent = payload
|
||||
result.senderCurve25519Key = olmEventContent.senderKey
|
||||
result.claimedEd25519Key = olmPayloadContent.keys!!.get("ed25519")
|
||||
result.senderCurve25519Key = senderKey
|
||||
result.claimedEd25519Key = keys["ed25519"]
|
||||
|
||||
return result
|
||||
}
|
||||
@ -167,7 +176,7 @@ internal class MXOlmDecryption(
|
||||
sessionIds = ArrayList(sessionIdsSet)
|
||||
}
|
||||
|
||||
val messageBody = message["body"] as String?
|
||||
val messageBody = message["body"] as? String
|
||||
var messageType: Int? = null
|
||||
|
||||
val typeAsVoid = message["type"]
|
||||
@ -210,7 +219,7 @@ internal class MXOlmDecryption(
|
||||
// not a prekey message, so it should have matched an existing session, but it
|
||||
// didn't work.
|
||||
|
||||
if (sessionIds.size == 0) {
|
||||
if (sessionIds.isEmpty()) {
|
||||
Timber.e("## decryptMessage() : No existing sessions")
|
||||
} else {
|
||||
Timber.e("## decryptMessage() : Error decrypting non-prekey message with existing sessions")
|
||||
@ -228,7 +237,7 @@ internal class MXOlmDecryption(
|
||||
return null
|
||||
}
|
||||
|
||||
Timber.v("## decryptMessage() : Created new inbound Olm session get id " + res["session_id"] + " with " + theirDeviceIdentityKey)
|
||||
Timber.v("## decryptMessage() : Created new inbound Olm session get id ${res["session_id"]} with $theirDeviceIdentityKey")
|
||||
|
||||
return res["payload"]
|
||||
}
|
||||
|
@ -24,10 +24,11 @@ import kotlinx.android.parcel.Parcelize
|
||||
fun EncryptedFileInfo.toElementToDecrypt(): ElementToDecrypt? {
|
||||
// Check the validity of some fields
|
||||
if (isValid()) {
|
||||
// It's valid so the data are here
|
||||
return ElementToDecrypt(
|
||||
iv = this.iv!!,
|
||||
k = this.key!!.k!!,
|
||||
sha256 = this.hashes!!["sha256"] ?: error("")
|
||||
iv = this.iv ?: "",
|
||||
k = this.key?.k ?: "",
|
||||
sha256 = this.hashes?.get("sha256") ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,6 @@ import im.vector.matrix.android.internal.crypto.keysbackup.tasks.*
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
||||
@ -388,8 +387,8 @@ internal class KeysBackup @Inject constructor(
|
||||
return keysBackupVersionTrust
|
||||
}
|
||||
|
||||
val mySigs: Map<String, *> = authData.signatures!![myUserId] as Map<String, *>
|
||||
if (mySigs.isEmpty()) {
|
||||
val mySigs = authData.signatures?.get(myUserId)
|
||||
if (mySigs.isNullOrEmpty()) {
|
||||
Timber.v("getKeysBackupTrust: Ignoring key backup because it lacks any signatures from this user")
|
||||
return keysBackupVersionTrust
|
||||
}
|
||||
@ -402,20 +401,21 @@ internal class KeysBackup @Inject constructor(
|
||||
deviceId = components[1]
|
||||
}
|
||||
|
||||
var device: MXDeviceInfo? = null
|
||||
if (deviceId != null) {
|
||||
device = cryptoStore.getUserDevice(deviceId, myUserId)
|
||||
|
||||
val device = cryptoStore.getUserDevice(deviceId, myUserId)
|
||||
var isSignatureValid = false
|
||||
|
||||
if (device == null) {
|
||||
Timber.v("getKeysBackupTrust: Signature from unknown device $deviceId")
|
||||
} else {
|
||||
try {
|
||||
olmDevice.verifySignature(device.fingerprint()!!, authData.signalableJSONDictionary(), mySigs[keyId] as String)
|
||||
isSignatureValid = true
|
||||
} catch (e: OlmException) {
|
||||
Timber.v("getKeysBackupTrust: Bad signature from device " + device.deviceId + " " + e.localizedMessage)
|
||||
val fingerprint = device.fingerprint()
|
||||
if (fingerprint != null) {
|
||||
try {
|
||||
olmDevice.verifySignature(fingerprint, authData.signalableJSONDictionary(), mySigs[keyId] as String)
|
||||
isSignatureValid = true
|
||||
} catch (e: OlmException) {
|
||||
Timber.v("getKeysBackupTrust: Bad signature from device " + device.deviceId + " " + e.localizedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
if (isSignatureValid && device.isVerified) {
|
||||
@ -452,8 +452,7 @@ internal class KeysBackup @Inject constructor(
|
||||
val myUserId = credentials.userId
|
||||
|
||||
// Get current signatures, or create an empty set
|
||||
val myUserSignatures = (authData.signatures!![myUserId]?.toMutableMap()
|
||||
?: HashMap())
|
||||
val myUserSignatures = authData.signatures?.get(myUserId)?.toMutableMap() ?: HashMap()
|
||||
|
||||
if (trust) {
|
||||
// Add current device signature
|
||||
@ -1027,8 +1026,7 @@ internal class KeysBackup @Inject constructor(
|
||||
|
||||
val authData = keysBackupData.getAuthDataAsMegolmBackupAuthData()
|
||||
|
||||
if (authData.signatures == null
|
||||
|| authData.publicKey.isBlank()) {
|
||||
if (authData?.signatures == null || authData.publicKey.isBlank()) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -54,9 +54,9 @@ open class KeysAlgorithmAndData {
|
||||
/**
|
||||
* Facility method to convert authData to a MegolmBackupAuthData object
|
||||
*/
|
||||
fun getAuthDataAsMegolmBackupAuthData(): MegolmBackupAuthData {
|
||||
fun getAuthDataAsMegolmBackupAuthData(): MegolmBackupAuthData? {
|
||||
return MoshiProvider.providesMoshi()
|
||||
.adapter(MegolmBackupAuthData::class.java)
|
||||
.fromJsonValue(authData)!!
|
||||
.fromJsonValue(authData)
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
package im.vector.matrix.android.internal.crypto.model
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
@ -107,30 +106,25 @@ data class MXDeviceInfo(
|
||||
* @return the fingerprint
|
||||
*/
|
||||
fun fingerprint(): String? {
|
||||
return if (null != keys && !TextUtils.isEmpty(deviceId)) {
|
||||
keys!!["ed25519:$deviceId"]
|
||||
} else null
|
||||
|
||||
return keys
|
||||
?.takeIf { !deviceId.isBlank() }
|
||||
?.get("ed25519:$deviceId")
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the identity key
|
||||
*/
|
||||
fun identityKey(): String? {
|
||||
return if (null != keys && !TextUtils.isEmpty(deviceId)) {
|
||||
keys!!["curve25519:$deviceId"]
|
||||
} else null
|
||||
|
||||
return keys
|
||||
?.takeIf { !deviceId.isBlank() }
|
||||
?.get("curve25519:$deviceId")
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the display name
|
||||
*/
|
||||
fun displayName(): String? {
|
||||
return if (null != unsigned) {
|
||||
unsigned!!["device_display_name"] as String?
|
||||
} else null
|
||||
|
||||
return unsigned?.get("device_display_name") as? String
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,9 +135,7 @@ data class MXDeviceInfo(
|
||||
|
||||
map["device_id"] = deviceId
|
||||
|
||||
if (null != userId) {
|
||||
map["user_id"] = userId!!
|
||||
}
|
||||
map["user_id"] = userId
|
||||
|
||||
if (null != algorithms) {
|
||||
map["algorithms"] = algorithms!!
|
||||
|
@ -54,7 +54,7 @@ class MXUsersDevicesMap<E> {
|
||||
*/
|
||||
fun getObject(userId: String?, deviceId: String?): E? {
|
||||
return if (userId?.isNotBlank() == true && deviceId?.isNotBlank() == true && map.containsKey(userId)) {
|
||||
map[userId]!![deviceId]
|
||||
map[userId]?.get(deviceId)
|
||||
} else null
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class MXUsersDevicesMap<E> {
|
||||
map[userId] = HashMap()
|
||||
}
|
||||
|
||||
map[userId]!![deviceId] = o
|
||||
map[userId]?.put(deviceId, o)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,27 +111,29 @@ class OlmInboundGroupSessionWrapper : Serializable {
|
||||
* @return the inbound group session as MegolmSessionData if the operation succeeds
|
||||
*/
|
||||
fun exportKeys(): MegolmSessionData? {
|
||||
var megolmSessionData: MegolmSessionData? = MegolmSessionData()
|
||||
|
||||
try {
|
||||
return try {
|
||||
if (null == forwardingCurve25519KeyChain) {
|
||||
forwardingCurve25519KeyChain = ArrayList()
|
||||
}
|
||||
|
||||
megolmSessionData!!.senderClaimedEd25519Key = keysClaimed!!["ed25519"]
|
||||
megolmSessionData.forwardingCurve25519KeyChain = ArrayList(forwardingCurve25519KeyChain!!)
|
||||
megolmSessionData.senderKey = senderKey
|
||||
megolmSessionData.senderClaimedKeys = keysClaimed
|
||||
megolmSessionData.roomId = roomId
|
||||
megolmSessionData.sessionId = olmInboundGroupSession!!.sessionIdentifier()
|
||||
megolmSessionData.sessionKey = olmInboundGroupSession!!.export(olmInboundGroupSession!!.firstKnownIndex)
|
||||
megolmSessionData.algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
||||
} catch (e: Exception) {
|
||||
megolmSessionData = null
|
||||
Timber.e(e, "## export() : senderKey " + senderKey + " failed")
|
||||
}
|
||||
if (keysClaimed == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return megolmSessionData
|
||||
MegolmSessionData().also {
|
||||
it.senderClaimedEd25519Key = keysClaimed?.get("ed25519")
|
||||
it.forwardingCurve25519KeyChain = ArrayList(forwardingCurve25519KeyChain!!)
|
||||
it.senderKey = senderKey
|
||||
it.senderClaimedKeys = keysClaimed
|
||||
it.roomId = roomId
|
||||
it.sessionId = olmInboundGroupSession!!.sessionIdentifier()
|
||||
it.sessionKey = olmInboundGroupSession!!.export(olmInboundGroupSession!!.firstKnownIndex)
|
||||
it.algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## export() : senderKey $senderKey failed")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,8 +53,8 @@ data class OlmPayloadContent(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromJsonString(str: String): OlmPayloadContent {
|
||||
return MoshiProvider.providesMoshi().adapter(OlmPayloadContent::class.java).fromJson(str)!!
|
||||
fun fromJsonString(str: String): OlmPayloadContent? {
|
||||
return MoshiProvider.providesMoshi().adapter(OlmPayloadContent::class.java).fromJson(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,17 +46,19 @@ internal class DefaultClaimOneTimeKeysForUsersDevice @Inject constructor(private
|
||||
Try {
|
||||
val map = MXUsersDevicesMap<MXKey>()
|
||||
|
||||
if (null != keysClaimResponse.oneTimeKeys) {
|
||||
for (userId in keysClaimResponse.oneTimeKeys!!.keys) {
|
||||
val mapByUserId = keysClaimResponse.oneTimeKeys!![userId]
|
||||
keysClaimResponse.oneTimeKeys?.let { oneTimeKeys ->
|
||||
for (userId in oneTimeKeys.keys) {
|
||||
val mapByUserId = oneTimeKeys[userId]
|
||||
|
||||
for (deviceId in mapByUserId!!.keys) {
|
||||
val mxKey = MXKey.from(mapByUserId[deviceId])
|
||||
if (mapByUserId != null) {
|
||||
for (deviceId in mapByUserId.keys) {
|
||||
val mxKey = MXKey.from(mapByUserId[deviceId])
|
||||
|
||||
if (mxKey != null) {
|
||||
map.setObject(userId, deviceId, mxKey)
|
||||
} else {
|
||||
Timber.e("## claimOneTimeKeysForUsersDevices : fail to create a MXKey")
|
||||
if (mxKey != null) {
|
||||
map.setObject(userId, deviceId, mxKey)
|
||||
} else {
|
||||
Timber.e("## claimOneTimeKeysForUsersDevices : fail to create a MXKey")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
|
||||
viewModel.keyVersionResult.observe(this, Observer { keyVersion ->
|
||||
|
||||
if (keyVersion != null && supportFragmentManager.fragments.isEmpty()) {
|
||||
val isBackupCreatedFromPassphrase = keyVersion.getAuthDataAsMegolmBackupAuthData().privateKeySalt != null
|
||||
val isBackupCreatedFromPassphrase = keyVersion.getAuthDataAsMegolmBackupAuthData()?.privateKeySalt != null
|
||||
if (isBackupCreatedFromPassphrase) {
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, KeysBackupRestoreFromPassphraseFragment.newInstance())
|
||||
|
Loading…
Reference in New Issue
Block a user