KeysBackup: some API parameters are mandatory, so stop considering them as optional and avoid using !!

Also fix an issue with Json name: `hash` -> `etag`
Add some `internal` modifier (not as much as I would like to)
var -> val
Remove unused code
This commit is contained in:
Benoit Marty 2020-10-30 16:14:33 +01:00
parent 14e7e5e9fd
commit 0bcf42dbb8
14 changed files with 122 additions and 125 deletions

View File

@ -245,7 +245,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
fun createFakeMegolmBackupCreationInfo(): MegolmBackupCreationInfo { fun createFakeMegolmBackupCreationInfo(): MegolmBackupCreationInfo {
return MegolmBackupCreationInfo( return MegolmBackupCreationInfo(
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
authData = createFakeMegolmBackupAuthData() authData = createFakeMegolmBackupAuthData(),
recoveryKey = "fake"
) )
} }

View File

@ -115,9 +115,8 @@ class KeysBackupTest : InstrumentedTest {
} }
assertEquals(MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, megolmBackupCreationInfo.algorithm) assertEquals(MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, megolmBackupCreationInfo.algorithm)
assertNotNull(megolmBackupCreationInfo.authData) assertNotNull(megolmBackupCreationInfo.authData.publicKey)
assertNotNull(megolmBackupCreationInfo.authData!!.publicKey) assertNotNull(megolmBackupCreationInfo.authData.signatures)
assertNotNull(megolmBackupCreationInfo.authData!!.signatures)
assertNotNull(megolmBackupCreationInfo.recoveryKey) assertNotNull(megolmBackupCreationInfo.recoveryKey)
stateObserver.stopAndCheckStates(null) stateObserver.stopAndCheckStates(null)

View File

@ -30,7 +30,6 @@ import org.matrix.android.sdk.api.listeners.StepProgressListener
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.MXOlmDevice
import org.matrix.android.sdk.internal.crypto.MegolmSessionData import org.matrix.android.sdk.internal.crypto.MegolmSessionData
@ -85,6 +84,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.internal.crypto.keysbackup.model.SignalableMegolmBackupAuthData
import org.matrix.olm.OlmException import org.matrix.olm.OlmException
import org.matrix.olm.OlmPkDecryption import org.matrix.olm.OlmPkDecryption
import org.matrix.olm.OlmPkEncryption import org.matrix.olm.OlmPkEncryption
@ -170,7 +170,7 @@ internal class DefaultKeysBackupService @Inject constructor(
runCatching { runCatching {
withContext(coroutineDispatchers.crypto) { withContext(coroutineDispatchers.crypto) {
val olmPkDecryption = OlmPkDecryption() val olmPkDecryption = OlmPkDecryption()
val megolmBackupAuthData = if (password != null) { val signalableMegolmBackupAuthData = if (password != null) {
// Generate a private key from the password // Generate a private key from the password
val backgroundProgressListener = if (progressListener == null) { val backgroundProgressListener = if (progressListener == null) {
null null
@ -189,7 +189,7 @@ internal class DefaultKeysBackupService @Inject constructor(
} }
val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener) val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener)
MegolmBackupAuthData( SignalableMegolmBackupAuthData(
publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey), publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey),
privateKeySalt = generatePrivateKeyResult.salt, privateKeySalt = generatePrivateKeyResult.salt,
privateKeyIterations = generatePrivateKeyResult.iterations privateKeyIterations = generatePrivateKeyResult.iterations
@ -197,14 +197,17 @@ internal class DefaultKeysBackupService @Inject constructor(
} else { } else {
val publicKey = olmPkDecryption.generateKey() val publicKey = olmPkDecryption.generateKey()
MegolmBackupAuthData( SignalableMegolmBackupAuthData(
publicKey = publicKey publicKey = publicKey
) )
} }
val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary()) val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableMegolmBackupAuthData.signalableJSONDictionary())
val signedMegolmBackupAuthData = megolmBackupAuthData.copy( val signedMegolmBackupAuthData = MegolmBackupAuthData(
publicKey = signalableMegolmBackupAuthData.publicKey,
privateKeySalt = signalableMegolmBackupAuthData.privateKeySalt,
privateKeyIterations = signalableMegolmBackupAuthData.privateKeyIterations,
signatures = objectSigner.signObject(canonicalJson) signatures = objectSigner.signObject(canonicalJson)
) )
@ -223,8 +226,7 @@ internal class DefaultKeysBackupService @Inject constructor(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val createKeysBackupVersionBody = CreateKeysBackupVersionBody( val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
algorithm = keysBackupCreationInfo.algorithm, algorithm = keysBackupCreationInfo.algorithm,
authData = MoshiProvider.providesMoshi().adapter(Map::class.java) authData = keysBackupCreationInfo.authData.toJsonDict()
.fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
) )
keysBackupStateManager.state = KeysBackupState.Enabling keysBackupStateManager.state = KeysBackupState.Enabling
@ -245,7 +247,7 @@ internal class DefaultKeysBackupService @Inject constructor(
version = data.version, version = data.version,
// We can consider that the server does not have keys yet // We can consider that the server does not have keys yet
count = 0, count = 0,
hash = null hash = ""
) )
enableKeysBackup(keyBackupVersion) enableKeysBackup(keyBackupVersion)
@ -267,7 +269,7 @@ internal class DefaultKeysBackupService @Inject constructor(
withContext(coroutineDispatchers.crypto) { withContext(coroutineDispatchers.crypto) {
// If we're currently backing up to this backup... stop. // If we're currently backing up to this backup... stop.
// (We start using it automatically in createKeysBackupVersion so this is symmetrical). // (We start using it automatically in createKeysBackupVersion so this is symmetrical).
if (keysBackupVersion != null && version == keysBackupVersion!!.version) { if (keysBackupVersion != null && version == keysBackupVersion?.version) {
resetKeysBackupData() resetKeysBackupData()
keysBackupVersion = null keysBackupVersion = null
keysBackupStateManager.state = KeysBackupState.Unknown keysBackupStateManager.state = KeysBackupState.Unknown
@ -408,10 +410,7 @@ internal class DefaultKeysBackupService @Inject constructor(
val keysBackupVersionTrust = KeysBackupVersionTrust() val keysBackupVersionTrust = KeysBackupVersionTrust()
val authData = keysBackupVersion.getAuthDataAsMegolmBackupAuthData() val authData = keysBackupVersion.getAuthDataAsMegolmBackupAuthData()
if (keysBackupVersion.algorithm == null if (authData == null || authData.publicKey.isEmpty() || authData.signatures.isEmpty()) {
|| authData == null
|| authData.publicKey.isEmpty()
|| authData.signatures.isNullOrEmpty()) {
Timber.v("getKeysBackupTrust: Key backup is absent or missing required data") Timber.v("getKeysBackupTrust: Key backup is absent or missing required data")
return keysBackupVersionTrust return keysBackupVersionTrust
} }
@ -479,7 +478,7 @@ internal class DefaultKeysBackupService @Inject constructor(
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.main) {
val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) { val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) {
// Get current signatures, or create an empty set // Get current signatures, or create an empty set
val myUserSignatures = authData.signatures?.get(userId)?.toMutableMap() ?: HashMap() val myUserSignatures = authData.signatures[userId].orEmpty().toMutableMap()
if (trust) { if (trust) {
// Add current device signature // Add current device signature
@ -498,26 +497,23 @@ internal class DefaultKeysBackupService @Inject constructor(
// Create an updated version of KeysVersionResult // Create an updated version of KeysVersionResult
val newMegolmBackupAuthData = authData.copy() val newMegolmBackupAuthData = authData.copy()
val newSignatures = newMegolmBackupAuthData.signatures!!.toMutableMap() val newSignatures = newMegolmBackupAuthData.signatures.toMutableMap()
newSignatures[userId] = myUserSignatures newSignatures[userId] = myUserSignatures
val newMegolmBackupAuthDataWithNewSignature = newMegolmBackupAuthData.copy( val newMegolmBackupAuthDataWithNewSignature = newMegolmBackupAuthData.copy(
signatures = newSignatures signatures = newSignatures
) )
val moshi = MoshiProvider.providesMoshi()
val adapter = moshi.adapter(Map::class.java)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
UpdateKeysBackupVersionBody( UpdateKeysBackupVersionBody(
algorithm = keysBackupVersion.algorithm, algorithm = keysBackupVersion.algorithm,
authData = adapter.fromJson(newMegolmBackupAuthDataWithNewSignature.toJsonString()) as Map<String, Any>?, authData = newMegolmBackupAuthDataWithNewSignature.toJsonDict(),
version = keysBackupVersion.version!!) version = keysBackupVersion.version)
} }
// And send it to the homeserver // And send it to the homeserver
updateKeysBackupVersionTask updateKeysBackupVersionTask
.configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version!!, updateKeysBackupVersionBody)) { .configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version, updateKeysBackupVersionBody)) {
this.callback = object : MatrixCallback<Unit> { this.callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
// Relaunch the state machine on this updated backup version // Relaunch the state machine on this updated backup version
@ -688,7 +684,7 @@ internal class DefaultKeysBackupService @Inject constructor(
stepProgressListener?.onStepProgress(StepProgressListener.Step.DownloadingKey) stepProgressListener?.onStepProgress(StepProgressListener.Step.DownloadingKey)
// Get backed up keys from the homeserver // Get backed up keys from the homeserver
val data = getKeys(sessionId, roomId, keysVersionResult.version!!) val data = getKeys(sessionId, roomId, keysVersionResult.version)
withContext(coroutineDispatchers.computation) { withContext(coroutineDispatchers.computation) {
val sessionsData = ArrayList<MegolmSessionData>() val sessionsData = ArrayList<MegolmSessionData>()
@ -1023,19 +1019,10 @@ internal class DefaultKeysBackupService @Inject constructor(
* @return the authentication if found and valid, null in other case * @return the authentication if found and valid, null in other case
*/ */
private fun getMegolmBackupAuthData(keysBackupData: KeysVersionResult): MegolmBackupAuthData? { private fun getMegolmBackupAuthData(keysBackupData: KeysVersionResult): MegolmBackupAuthData? {
if (keysBackupData.version.isNullOrBlank() return keysBackupData
|| keysBackupData.algorithm != MXCRYPTO_ALGORITHM_MEGOLM_BACKUP .takeIf { it.version.isNotEmpty() && it.algorithm == MXCRYPTO_ALGORITHM_MEGOLM_BACKUP }
|| keysBackupData.authData == null) { ?.getAuthDataAsMegolmBackupAuthData()
return null ?.takeIf { it.publicKey.isNotEmpty() }
}
val authData = keysBackupData.getAuthDataAsMegolmBackupAuthData()
if (authData?.signatures == null || authData.publicKey.isBlank()) {
return null
}
return authData
} }
/** /**
@ -1123,34 +1110,29 @@ internal class DefaultKeysBackupService @Inject constructor(
* @param keysVersionResult backup information object as returned by [getCurrentVersion]. * @param keysVersionResult backup information object as returned by [getCurrentVersion].
*/ */
private fun enableKeysBackup(keysVersionResult: KeysVersionResult) { private fun enableKeysBackup(keysVersionResult: KeysVersionResult) {
if (keysVersionResult.authData != null) { val retrievedMegolmBackupAuthData = keysVersionResult.getAuthDataAsMegolmBackupAuthData()
val retrievedMegolmBackupAuthData = keysVersionResult.getAuthDataAsMegolmBackupAuthData()
if (retrievedMegolmBackupAuthData != null) { if (retrievedMegolmBackupAuthData != null) {
keysBackupVersion = keysVersionResult keysBackupVersion = keysVersionResult
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
cryptoStore.setKeyBackupVersion(keysVersionResult.version) cryptoStore.setKeyBackupVersion(keysVersionResult.version)
}
onServerDataRetrieved(keysVersionResult.count, keysVersionResult.hash)
try {
backupOlmPkEncryption = OlmPkEncryption().apply {
setRecipientKey(retrievedMegolmBackupAuthData.publicKey)
}
} catch (e: OlmException) {
Timber.e(e, "OlmException")
keysBackupStateManager.state = KeysBackupState.Disabled
return
}
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
maybeBackupKeys()
} else {
Timber.e("Invalid authentication data")
keysBackupStateManager.state = KeysBackupState.Disabled
} }
onServerDataRetrieved(keysVersionResult.count, keysVersionResult.hash)
try {
backupOlmPkEncryption = OlmPkEncryption().apply {
setRecipientKey(retrievedMegolmBackupAuthData.publicKey)
}
} catch (e: OlmException) {
Timber.e(e, "OlmException")
keysBackupStateManager.state = KeysBackupState.Disabled
return
}
keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
maybeBackupKeys()
} else { } else {
Timber.e("Invalid authentication data") Timber.e("Invalid authentication data")
keysBackupStateManager.state = KeysBackupState.Disabled keysBackupStateManager.state = KeysBackupState.Disabled
@ -1160,11 +1142,11 @@ internal class DefaultKeysBackupService @Inject constructor(
/** /**
* Update the DB with data fetch from the server * Update the DB with data fetch from the server
*/ */
private fun onServerDataRetrieved(count: Int?, hash: String?) { private fun onServerDataRetrieved(count: Int?, etag: String?) {
cryptoStore.setKeysBackupData(KeysBackupDataEntity() cryptoStore.setKeysBackupData(KeysBackupDataEntity()
.apply { .apply {
backupLastServerNumberOfKeys = count backupLastServerNumberOfKeys = count
backupLastServerHash = hash backupLastServerHash = etag
} }
) )
} }
@ -1316,7 +1298,7 @@ internal class DefaultKeysBackupService @Inject constructor(
// Make the request // Make the request
storeSessionDataTask storeSessionDataTask
.configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version!!, keysBackupData)) { .configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version, keysBackupData)) {
this.callback = sendingRequestCallback this.callback = sendingRequestCallback
} }
.executeBy(taskExecutor) .executeBy(taskExecutor)
@ -1337,8 +1319,7 @@ internal class DefaultKeysBackupService @Inject constructor(
"algorithm" to sessionData!!.algorithm, "algorithm" to sessionData!!.algorithm,
"sender_key" to sessionData.senderKey, "sender_key" to sessionData.senderKey,
"sender_claimed_keys" to sessionData.senderClaimedKeys, "sender_claimed_keys" to sessionData.senderClaimedKeys,
"forwarding_curve25519_key_chain" to (sessionData.forwardingCurve25519KeyChain "forwarding_curve25519_key_chain" to (sessionData.forwardingCurve25519KeyChain.orEmpty()),
?: ArrayList<Any>()),
"session_key" to sessionData.sessionKey) "session_key" to sessionData.sessionKey)
var encryptedSessionBackupData: OlmPkMessage? = null var encryptedSessionBackupData: OlmPkMessage? = null
@ -1379,9 +1360,9 @@ internal class DefaultKeysBackupService @Inject constructor(
val jsonObject = keyBackupData.sessionData val jsonObject = keyBackupData.sessionData
val ciphertext = jsonObject?.get("ciphertext")?.toString() val ciphertext = jsonObject["ciphertext"]?.toString()
val mac = jsonObject?.get("mac")?.toString() val mac = jsonObject["mac"]?.toString()
val ephemeralKey = jsonObject?.get("ephemeral")?.toString() val ephemeralKey = jsonObject["ephemeral"]?.toString()
if (ciphertext != null && mac != null && ephemeralKey != null) { if (ciphertext != null && mac != null && ephemeralKey != null) {
val encrypted = OlmPkMessage() val encrypted = OlmPkMessage()
@ -1426,8 +1407,7 @@ internal class DefaultKeysBackupService @Inject constructor(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val createKeysBackupVersionBody = CreateKeysBackupVersionBody( val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
algorithm = keysBackupCreationInfo.algorithm, algorithm = keysBackupCreationInfo.algorithm,
authData = MoshiProvider.providesMoshi().adapter(Map::class.java) authData = keysBackupCreationInfo.authData.toJsonDict()
.fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
) )
createKeysBackupVersionTask createKeysBackupVersionTask

View File

@ -35,7 +35,7 @@ import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
/** /**
* Ref: https://github.com/uhoreg/matrix-doc/blob/e2e_backup/proposals/1219-storing-megolm-keys-serverside.md * Ref: https://matrix.org/docs/spec/client_server/unstable#server-side-key-backups
*/ */
internal interface RoomKeysApi { internal interface RoomKeysApi {

View File

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.model
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
/** /**
@ -30,7 +31,7 @@ data class MegolmBackupAuthData(
* The curve25519 public key used to encrypt the backups. * The curve25519 public key used to encrypt the backups.
*/ */
@Json(name = "public_key") @Json(name = "public_key")
val publicKey: String = "", val publicKey: String,
/** /**
* In case of a backup created from a password, the salt associated with the backup * In case of a backup created from a password, the salt associated with the backup
@ -50,20 +51,38 @@ data class MegolmBackupAuthData(
* userId -> (deviceSignKeyId -> signature) * userId -> (deviceSignKeyId -> signature)
*/ */
@Json(name = "signatures") @Json(name = "signatures")
val signatures: Map<String, Map<String, String>>? = null val signatures: Map<String, Map<String, String>>
) { ) {
fun toJsonString(): String { fun toJsonDict(): JsonDict {
return MoshiProvider.providesMoshi() val moshi = MoshiProvider.providesMoshi()
val adapter = moshi.adapter(Map::class.java)
return moshi
.adapter(MegolmBackupAuthData::class.java) .adapter(MegolmBackupAuthData::class.java)
.toJson(this) .toJson(this)
.let {
@Suppress("UNCHECKED_CAST")
adapter.fromJson(it) as JsonDict
}
} }
/** fun signalableJSONDictionary(): JsonDict {
* Same as the parent [MXJSONModel JSONDictionary] but return only return SignalableMegolmBackupAuthData(
* data that must be signed. publicKey = publicKey,
*/ privateKeySalt = privateKeySalt,
fun signalableJSONDictionary(): Map<String, Any> = HashMap<String, Any>().apply { privateKeyIterations = privateKeyIterations
)
.signalableJSONDictionary()
}
}
internal data class SignalableMegolmBackupAuthData(
val publicKey: String,
val privateKeySalt: String? = null,
val privateKeyIterations: Int? = null
) {
fun signalableJSONDictionary(): JsonDict = HashMap<String, Any>().apply {
put("public_key", publicKey) put("public_key", publicKey)
privateKeySalt?.let { privateKeySalt?.let {

View File

@ -23,15 +23,15 @@ data class MegolmBackupCreationInfo(
/** /**
* The algorithm used for storing backups [org.matrix.androidsdk.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP]. * The algorithm used for storing backups [org.matrix.androidsdk.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP].
*/ */
val algorithm: String = "", val algorithm: String,
/** /**
* Authentication data. * Authentication data.
*/ */
val authData: MegolmBackupAuthData? = null, val authData: MegolmBackupAuthData,
/** /**
* The Base58 recovery key. * The Base58 recovery key.
*/ */
val recoveryKey: String = "" val recoveryKey: String
) )

View File

@ -16,15 +16,16 @@
package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class BackupKeysResult( internal data class BackupKeysResult(
// The hash value which is an opaque string representing stored keys in the backup // The hash value which is an opaque string representing stored keys in the backup
var hash: String? = null, @Json(name = "etag")
val hash: String,
// The number of keys stored in the backup. // The number of keys stored in the backup.
var count: Int? = null @Json(name = "count")
val count: Int
) )

View File

@ -21,17 +21,17 @@ import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class CreateKeysBackupVersionBody( internal data class CreateKeysBackupVersionBody(
/** /**
* The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
*/ */
@Json(name = "algorithm") @Json(name = "algorithm")
override val algorithm: String? = null, override val algorithm: String,
/** /**
* algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2"
* see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
*/ */
@Json(name = "auth_data") @Json(name = "auth_data")
override val authData: JsonDict? = null override val authData: JsonDict
) : KeysAlgorithmAndData ) : KeysAlgorithmAndData

View File

@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.network.parsing.ForceToBoolean import org.matrix.android.sdk.internal.network.parsing.ForceToBoolean
/** /**
@ -30,13 +30,13 @@ data class KeyBackupData(
* Required. The index of the first message in the session that the key can decrypt. * Required. The index of the first message in the session that the key can decrypt.
*/ */
@Json(name = "first_message_index") @Json(name = "first_message_index")
val firstMessageIndex: Long = 0, val firstMessageIndex: Long,
/** /**
* Required. The number of times this key has been forwarded. * Required. The number of times this key has been forwarded.
*/ */
@Json(name = "forwarded_count") @Json(name = "forwarded_count")
val forwardedCount: Int = 0, val forwardedCount: Int,
/** /**
* Whether the device backing up the key has verified the device that the key is from. * Whether the device backing up the key has verified the device that the key is from.
@ -44,16 +44,11 @@ data class KeyBackupData(
*/ */
@ForceToBoolean @ForceToBoolean
@Json(name = "is_verified") @Json(name = "is_verified")
val isVerified: Boolean = false, val isVerified: Boolean,
/** /**
* Algorithm-dependent data. * Algorithm-dependent data.
*/ */
@Json(name = "session_data") @Json(name = "session_data")
val sessionData: Map<String, Any>? = null val sessionData: JsonDict
) { )
fun toJsonString(): String {
return MoshiProvider.providesMoshi().adapter(KeyBackupData::class.java).toJson(this)
}
}

View File

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupAuthData import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupAuthData
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
@ -37,24 +38,25 @@ import org.matrix.android.sdk.internal.di.MoshiProvider
* } * }
* </pre> * </pre>
*/ */
interface KeysAlgorithmAndData { internal interface KeysAlgorithmAndData {
/** /**
* The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
*/ */
val algorithm: String? val algorithm: String
/** /**
* algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
*/ */
val authData: JsonDict? val authData: JsonDict
/** /**
* Facility method to convert authData to a MegolmBackupAuthData object * Facility method to convert authData to a MegolmBackupAuthData object
*/ */
fun getAuthDataAsMegolmBackupAuthData(): MegolmBackupAuthData? { fun getAuthDataAsMegolmBackupAuthData(): MegolmBackupAuthData? {
return MoshiProvider.providesMoshi() return MoshiProvider.providesMoshi()
.adapter(MegolmBackupAuthData::class.java) .takeIf { algorithm == MXCRYPTO_ALGORITHM_MEGOLM_BACKUP }
.fromJsonValue(authData) ?.adapter(MegolmBackupAuthData::class.java)
?.fromJsonValue(authData)
} }
} }

View File

@ -23,5 +23,5 @@ import com.squareup.moshi.JsonClass
data class KeysVersion( data class KeysVersion(
// the keys backup version // the keys backup version
@Json(name = "version") @Json(name = "version")
val version: String? = null val version: String
) )

View File

@ -26,24 +26,24 @@ data class KeysVersionResult(
* The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
*/ */
@Json(name = "algorithm") @Json(name = "algorithm")
override val algorithm: String? = null, override val algorithm: String,
/** /**
* algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2"
* see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
*/ */
@Json(name = "auth_data") @Json(name = "auth_data")
override val authData: JsonDict? = null, override val authData: JsonDict,
// the backup version // the backup version
@Json(name = "version") @Json(name = "version")
val version: String? = null, val version: String,
// The hash value which is an opaque string representing stored keys in the backup // The hash value which is an opaque string representing stored keys in the backup
@Json(name = "hash") @Json(name = "etag")
val hash: String? = null, val hash: String,
// The number of keys stored in the backup. // The number of keys stored in the backup.
@Json(name = "count") @Json(name = "count")
val count: Int? = null val count: Int
) : KeysAlgorithmAndData ) : KeysAlgorithmAndData

View File

@ -26,16 +26,16 @@ data class UpdateKeysBackupVersionBody(
* The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
*/ */
@Json(name = "algorithm") @Json(name = "algorithm")
override val algorithm: String? = null, override val algorithm: String,
/** /**
* algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2"
* see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData] * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
*/ */
@Json(name = "auth_data") @Json(name = "auth_data")
override val authData: JsonDict? = null, override val authData: JsonDict,
// the backup version, mandatory // Optional. The backup version. If present, must be the same as the path parameter.
@Json(name = "version") @Json(name = "version")
val version: String val version: String? = null
) : KeysAlgorithmAndData ) : KeysAlgorithmAndData

View File

@ -103,7 +103,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
} else { } else {
// we need to get existing backup passphrase/key and convert to SSSS // we need to get existing backup passphrase/key and convert to SSSS
val keyVersion = awaitCallback<KeysVersionResult?> { val keyVersion = awaitCallback<KeysVersionResult?> {
session.cryptoService().keysBackupService().getVersion(version.version ?: "", it) session.cryptoService().keysBackupService().getVersion(version.version, it)
} }
if (keyVersion == null) { if (keyVersion == null) {
// strange case... just finish? // strange case... just finish?