mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Merge pull request #1172 from vector-im/feature/ensure_olm_account_unicity
Feature/ensure olm account unicity
This commit is contained in:
commit
1d46b523b9
5 changed files with 67 additions and 62 deletions
|
@ -10,6 +10,7 @@ Improvements 🙌:
|
|||
|
||||
Bugfix 🐛:
|
||||
- Missing avatar/displayname after verification request message (#841)
|
||||
- Crypto | RiotX sometimes rotate the current device keys (#1170)
|
||||
- RiotX can't restore cross signing keys saved by web in SSSS (#1174)
|
||||
|
||||
Translations 🗣:
|
||||
|
|
|
@ -59,9 +59,6 @@ internal class MXOlmDevice @Inject constructor(
|
|||
var deviceEd25519Key: String? = null
|
||||
private set
|
||||
|
||||
// The OLM lib account instance.
|
||||
private var olmAccount: OlmAccount? = null
|
||||
|
||||
// The OLM lib utility instance.
|
||||
private var olmUtility: OlmUtility? = null
|
||||
|
||||
|
@ -86,20 +83,11 @@ internal class MXOlmDevice @Inject constructor(
|
|||
|
||||
init {
|
||||
// Retrieve the account from the store
|
||||
olmAccount = store.getAccount()
|
||||
|
||||
if (null == olmAccount) {
|
||||
Timber.v("MXOlmDevice : create a new olm account")
|
||||
// Else, create it
|
||||
try {
|
||||
olmAccount = OlmAccount()
|
||||
store.storeAccount(olmAccount!!)
|
||||
store.getOrCreateOlmAccount()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "MXOlmDevice : cannot initialize olmAccount")
|
||||
}
|
||||
} else {
|
||||
Timber.v("MXOlmDevice : use an existing account")
|
||||
}
|
||||
|
||||
try {
|
||||
olmUtility = OlmUtility()
|
||||
|
@ -109,13 +97,13 @@ internal class MXOlmDevice @Inject constructor(
|
|||
}
|
||||
|
||||
try {
|
||||
deviceCurve25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY]
|
||||
deviceCurve25519Key = store.getOlmAccount().identityKeys()[OlmAccount.JSON_KEY_IDENTITY_KEY]
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## MXOlmDevice : cannot find ${OlmAccount.JSON_KEY_IDENTITY_KEY} with error")
|
||||
}
|
||||
|
||||
try {
|
||||
deviceEd25519Key = olmAccount!!.identityKeys()[OlmAccount.JSON_KEY_FINGER_PRINT_KEY]
|
||||
deviceEd25519Key = store.getOlmAccount().identityKeys()[OlmAccount.JSON_KEY_FINGER_PRINT_KEY]
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## MXOlmDevice : cannot find ${OlmAccount.JSON_KEY_FINGER_PRINT_KEY} with error")
|
||||
}
|
||||
|
@ -126,7 +114,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
*/
|
||||
fun getOneTimeKeys(): Map<String, Map<String, String>>? {
|
||||
try {
|
||||
return olmAccount!!.oneTimeKeys()
|
||||
return store.getOlmAccount().oneTimeKeys()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## getOneTimeKeys() : failed")
|
||||
}
|
||||
|
@ -138,14 +126,13 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* @return The maximum number of one-time keys the olm account can store.
|
||||
*/
|
||||
fun getMaxNumberOfOneTimeKeys(): Long {
|
||||
return olmAccount?.maxOneTimeKeys() ?: -1
|
||||
return store.getOlmAccount().maxOneTimeKeys()
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the instance
|
||||
*/
|
||||
fun release() {
|
||||
olmAccount?.releaseAccount()
|
||||
olmUtility?.releaseUtility()
|
||||
}
|
||||
|
||||
|
@ -157,7 +144,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
*/
|
||||
fun signMessage(message: String): String? {
|
||||
try {
|
||||
return olmAccount!!.signMessage(message)
|
||||
return store.getOlmAccount().signMessage(message)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## signMessage() : failed")
|
||||
}
|
||||
|
@ -170,8 +157,8 @@ internal class MXOlmDevice @Inject constructor(
|
|||
*/
|
||||
fun markKeysAsPublished() {
|
||||
try {
|
||||
olmAccount!!.markOneTimeKeysAsPublished()
|
||||
store.storeAccount(olmAccount!!)
|
||||
store.getOlmAccount().markOneTimeKeysAsPublished()
|
||||
store.saveOlmAccount()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## markKeysAsPublished() : failed")
|
||||
}
|
||||
|
@ -184,8 +171,8 @@ internal class MXOlmDevice @Inject constructor(
|
|||
*/
|
||||
fun generateOneTimeKeys(numKeys: Int) {
|
||||
try {
|
||||
olmAccount!!.generateOneTimeKeys(numKeys)
|
||||
store.storeAccount(olmAccount!!)
|
||||
store.getOlmAccount().generateOneTimeKeys(numKeys)
|
||||
store.saveOlmAccount()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## generateOneTimeKeys() : failed")
|
||||
}
|
||||
|
@ -205,7 +192,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
|
||||
try {
|
||||
olmSession = OlmSession()
|
||||
olmSession.initOutboundSession(olmAccount!!, theirIdentityKey, theirOneTimeKey)
|
||||
olmSession.initOutboundSession(store.getOlmAccount(), theirIdentityKey, theirOneTimeKey)
|
||||
|
||||
val olmSessionWrapper = OlmSessionWrapper(olmSession, 0)
|
||||
|
||||
|
@ -245,7 +232,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
try {
|
||||
try {
|
||||
olmSession = OlmSession()
|
||||
olmSession.initInboundSessionFrom(olmAccount!!, theirDeviceIdentityKey, ciphertext)
|
||||
olmSession.initInboundSessionFrom(store.getOlmAccount(), theirDeviceIdentityKey, ciphertext)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## createInboundSession() : the session creation failed")
|
||||
return null
|
||||
|
@ -254,8 +241,8 @@ internal class MXOlmDevice @Inject constructor(
|
|||
Timber.v("## createInboundSession() : sessionId: ${olmSession.sessionIdentifier()}")
|
||||
|
||||
try {
|
||||
olmAccount!!.removeOneTimeKeys(olmSession)
|
||||
store.storeAccount(olmAccount!!)
|
||||
store.getOlmAccount().removeOneTimeKeys(olmSession)
|
||||
store.saveOlmAccount()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## createInboundSession() : removeOneTimeKeys failed")
|
||||
}
|
||||
|
|
|
@ -49,7 +49,9 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* @return the olm account
|
||||
*/
|
||||
fun getAccount(): OlmAccount?
|
||||
fun getOlmAccount(): OlmAccount
|
||||
|
||||
fun getOrCreateOlmAccount(): OlmAccount
|
||||
|
||||
/**
|
||||
* Retrieve the known inbound group sessions.
|
||||
|
@ -159,7 +161,7 @@ internal interface IMXCryptoStore {
|
|||
*
|
||||
* @param account the account to save
|
||||
*/
|
||||
fun storeAccount(account: OlmAccount)
|
||||
fun saveOlmAccount()
|
||||
|
||||
/**
|
||||
* Store a device for a user.
|
||||
|
|
|
@ -122,27 +122,7 @@ internal class RealmCryptoStore @Inject constructor(
|
|||
.setRealmConfiguration(realmConfiguration)
|
||||
.build()
|
||||
|
||||
/* ==========================================================================================
|
||||
* Other data
|
||||
* ========================================================================================== */
|
||||
|
||||
override fun hasData(): Boolean {
|
||||
return doWithRealm(realmConfiguration) {
|
||||
!it.isEmpty
|
||||
// Check if there is a MetaData object
|
||||
&& it.where<CryptoMetadataEntity>().count() > 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteStore() {
|
||||
doRealmTransaction(realmConfiguration) {
|
||||
it.deleteAll()
|
||||
}
|
||||
}
|
||||
|
||||
override fun open() {
|
||||
realmLocker = Realm.getInstance(realmConfiguration)
|
||||
|
||||
init {
|
||||
// Ensure CryptoMetadataEntity is inserted in DB
|
||||
doRealmTransaction(realmConfiguration) { realm ->
|
||||
var currentMetadata = realm.where<CryptoMetadataEntity>().findFirst()
|
||||
|
@ -173,6 +153,27 @@ internal class RealmCryptoStore @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
/* ==========================================================================================
|
||||
* Other data
|
||||
* ========================================================================================== */
|
||||
|
||||
override fun hasData(): Boolean {
|
||||
return doWithRealm(realmConfiguration) {
|
||||
!it.isEmpty
|
||||
// Check if there is a MetaData object
|
||||
&& it.where<CryptoMetadataEntity>().count() > 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteStore() {
|
||||
doRealmTransaction(realmConfiguration) {
|
||||
it.deleteAll()
|
||||
}
|
||||
}
|
||||
|
||||
override fun open() {
|
||||
realmLocker = Realm.getInstance(realmConfiguration)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
olmSessionsToRelease.forEach {
|
||||
|
@ -203,20 +204,31 @@ internal class RealmCryptoStore @Inject constructor(
|
|||
}?.deviceId ?: ""
|
||||
}
|
||||
|
||||
override fun storeAccount(account: OlmAccount) {
|
||||
olmAccount = account
|
||||
|
||||
override fun saveOlmAccount() {
|
||||
doRealmTransaction(realmConfiguration) {
|
||||
it.where<CryptoMetadataEntity>().findFirst()?.putOlmAccount(account)
|
||||
it.where<CryptoMetadataEntity>().findFirst()?.putOlmAccount(olmAccount)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAccount(): OlmAccount? {
|
||||
if (olmAccount == null) {
|
||||
olmAccount = doRealmQueryAndCopy(realmConfiguration) { it.where<CryptoMetadataEntity>().findFirst() }?.getOlmAccount()
|
||||
override fun getOlmAccount(): OlmAccount {
|
||||
return olmAccount!!
|
||||
}
|
||||
|
||||
return olmAccount
|
||||
override fun getOrCreateOlmAccount(): OlmAccount {
|
||||
doRealmTransaction(realmConfiguration) {
|
||||
val metaData = it.where<CryptoMetadataEntity>().findFirst()
|
||||
val existing = metaData!!.getOlmAccount()
|
||||
if (existing == null) {
|
||||
Timber.d("## Crypto Creating olm account")
|
||||
val created = OlmAccount()
|
||||
metaData.putOlmAccount(created)
|
||||
olmAccount = created
|
||||
} else {
|
||||
Timber.d("## Crypto Access existing account")
|
||||
olmAccount = existing
|
||||
}
|
||||
}
|
||||
return olmAccount!!
|
||||
}
|
||||
|
||||
override fun storeUserDevice(userId: String?, deviceInfo: CryptoDeviceInfo?) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import im.vector.matrix.android.internal.network.executeRequest
|
|||
import im.vector.matrix.android.internal.task.Task
|
||||
import im.vector.matrix.android.internal.util.convertToUTF8
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface UploadKeysTask : Task<UploadKeysTask.Params, KeysUploadResponse> {
|
||||
|
@ -50,6 +51,8 @@ internal class DefaultUploadKeysTask @Inject constructor(
|
|||
oneTimeKeys = params.oneTimeKeys
|
||||
)
|
||||
|
||||
Timber.i("## Uploading device keys -> $body")
|
||||
|
||||
return executeRequest(eventBus) {
|
||||
apiCall = if (encodedDeviceId.isBlank()) {
|
||||
cryptoApi.uploadKeys(body)
|
||||
|
|
Loading…
Reference in a new issue