Merge sql crypto store implementation
This commit is contained in:
commit
9a4cad1e45
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,3 +14,4 @@
|
|||||||
/tmp
|
/tmp
|
||||||
|
|
||||||
ktlint
|
ktlint
|
||||||
|
.idea
|
||||||
|
19
CHANGES.md
19
CHANGES.md
@ -2,52 +2,40 @@ Changes in RiotX 0.19.0 (2020-XX-XX)
|
|||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features ✨:
|
Features ✨:
|
||||||
- Change password (#528)
|
|
||||||
- Cross-Signing | Support SSSS secret sharing (#944)
|
- Cross-Signing | Support SSSS secret sharing (#944)
|
||||||
- Cross-Signing | Verify new session from existing session (#1134)
|
- Cross-Signing | Verify new session from existing session (#1134)
|
||||||
- Cross-Signing | Bootstraping cross signing with 4S from mobile (#985)
|
- Cross-Signing | Bootstraping cross signing with 4S from mobile (#985)
|
||||||
- Save media files to Gallery (#973)
|
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
- Verification DM / Handle concurrent .start after .ready (#794)
|
- Verification DM / Handle concurrent .start after .ready (#794)
|
||||||
- Reimplementation of multiple attachment picker
|
|
||||||
- Cross-Signing | Update Shield Logic for DM (#963)
|
- Cross-Signing | Update Shield Logic for DM (#963)
|
||||||
- Cross-Signing | Complete security new session design update (#1135)
|
- Cross-Signing | Complete security new session design update (#1135)
|
||||||
- Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201)
|
- Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201)
|
||||||
- Cross-Signing | Gossip key backup recovery key (#1200)
|
- Cross-Signing | Gossip key backup recovery key (#1200)
|
||||||
- Show room encryption status as a bubble tile (#1078)
|
- Show room encryption status as a bubble tile (#1078)
|
||||||
- UX/UI | Add indicator to home tab on invite (#957)
|
|
||||||
- Cross-Signing | Restore history after recover from passphrase (#1214)
|
- Cross-Signing | Restore history after recover from passphrase (#1214)
|
||||||
- Cross-Sign | QR code scan confirmation screens design update (#1187)
|
- Cross-Sign | QR code scan confirmation screens design update (#1187)
|
||||||
- Emoji Verification | It's not the same butterfly! (#1220)
|
- Emoji Verification | It's not the same butterfly! (#1220)
|
||||||
- Cross-Signing | Composer decoration: shields (#1077)
|
|
||||||
- Cross-Signing | Migrate existing keybackup to cross signing with 4S from mobile (#1197)
|
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Fix summary notification staying after "mark as read"
|
|
||||||
- Missing avatar/displayname after verification request message (#841)
|
- Missing avatar/displayname after verification request message (#841)
|
||||||
- Crypto | RiotX sometimes rotate the current device keys (#1170)
|
- Crypto | RiotX sometimes rotate the current device keys (#1170)
|
||||||
- RiotX can't restore cross signing keys saved by web in SSSS (#1174)
|
- RiotX can't restore cross signing keys saved by web in SSSS (#1174)
|
||||||
- Cross- Signing | After signin in new session, verification paper trail in DM is off (#1191)
|
- Cross- Signing | After signin in new session, verification paper trail in DM is off (#1191)
|
||||||
- Failed to encrypt message in room (message stays in red), [thanks to pwr22] (#925)
|
- Failed to encrypt message in room (message stays in red), [thanks to pwr22] (#925)
|
||||||
- Cross-Signing | web <-> riotX After QR code scan, gossiping fails (#1210)
|
- Cross-Signing | web <-> riotX After QR code scan, gossiping fails (#1210)
|
||||||
- Fix crash when trying to download file without internet connection (#1229)
|
|
||||||
- Local echo are not updated in timeline (for failed & encrypted states)
|
|
||||||
- Render image event even if thumbnail_info does not have mimetype defined (#1209)
|
|
||||||
- RiotX now uses as many threads as it needs to do work and send messages (#1221)
|
|
||||||
- Fix issue with media path (#1227)
|
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
||||||
SDK API changes ⚠️:
|
SDK API changes ⚠️:
|
||||||
- Increase targetSdkVersion to 29
|
- Implementation of SqlCryptoStore on top of SQLDelight
|
||||||
|
|
||||||
Build 🧱:
|
Build 🧱:
|
||||||
- Compile with Android SDK 29 (Android Q)
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
- Add a setting to prevent screenshots of the application, disabled by default (#1027)
|
|
||||||
- Increase File Logger capacities ( + use dev log preferences)
|
- Increase File Logger capacities ( + use dev log preferences)
|
||||||
|
|
||||||
Changes in RiotX 0.18.1 (2020-03-17)
|
Changes in RiotX 0.18.1 (2020-03-17)
|
||||||
@ -456,7 +444,6 @@ Bugfix:
|
|||||||
- Fix messages with empty `in_reply_to` not rendering (#447)
|
- Fix messages with empty `in_reply_to` not rendering (#447)
|
||||||
- Fix clear cache (#408) and Logout (#205)
|
- Fix clear cache (#408) and Logout (#205)
|
||||||
- Fix `(edited)` link can be copied to clipboard (#402)
|
- Fix `(edited)` link can be copied to clipboard (#402)
|
||||||
- KeyBackup / SSSS | Should get the key from SSSS instead of asking recovery Key (#1163)
|
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
- Split APK: generate one APK per arch, to reduce APK size of about 30%
|
- Split APK: generate one APK per arch, to reduce APK size of about 30%
|
||||||
|
@ -71,6 +71,10 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packagingOptions {
|
||||||
|
pickFirst 'META-INF/kotlinx-coroutines-core.kotlin_module'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static def gitRevision() {
|
static def gitRevision() {
|
||||||
|
@ -18,14 +18,18 @@ package im.vector.matrix.android.internal.crypto.verification.qrcode
|
|||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import im.vector.matrix.android.InstrumentedTest
|
import im.vector.matrix.android.InstrumentedTest
|
||||||
|
import im.vector.matrix.android.api.session.crypto.verification.PendingVerificationRequest
|
||||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
|
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
|
||||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationService
|
import im.vector.matrix.android.api.session.crypto.verification.VerificationService
|
||||||
|
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||||
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
|
||||||
import im.vector.matrix.android.common.CommonTestHelper
|
import im.vector.matrix.android.common.CommonTestHelper
|
||||||
import im.vector.matrix.android.common.CryptoTestHelper
|
import im.vector.matrix.android.common.CryptoTestHelper
|
||||||
import im.vector.matrix.android.common.TestConstants
|
import im.vector.matrix.android.common.TestConstants
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||||
import im.vector.matrix.android.api.session.crypto.verification.PendingVerificationRequest
|
|
||||||
import org.amshove.kluent.shouldBe
|
import org.amshove.kluent.shouldBe
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@ -229,4 +233,46 @@ class VerificationTest : InstrumentedTest {
|
|||||||
|
|
||||||
cryptoTestData.cleanUp(mTestHelper)
|
cryptoTestData.cleanUp(mTestHelper)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_alice_sends_text_message_and_bob_can_decrypt() {
|
||||||
|
val lock = CountDownLatch(1)
|
||||||
|
|
||||||
|
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
|
|
||||||
|
val aliceSession = cryptoTestData.firstSession
|
||||||
|
val bobSession = cryptoTestData.secondSession!!
|
||||||
|
|
||||||
|
val roomFromBobPOV = bobSession.getRoom(cryptoTestData.roomId)!!
|
||||||
|
|
||||||
|
aliceSession.getRoom(cryptoTestData.roomId)!!.sendTextMessage("test")
|
||||||
|
|
||||||
|
val bobEventsListener = object : Timeline.Listener {
|
||||||
|
override fun onTimelineFailure(throwable: Throwable) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewTimelineEvents(eventIds: List<String>) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
|
||||||
|
if (snapshot.isNotEmpty() && snapshot.first().root.isEncrypted()) {
|
||||||
|
lock.countDown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(20))
|
||||||
|
bobTimeline.start()
|
||||||
|
bobTimeline.addListener(bobEventsListener)
|
||||||
|
|
||||||
|
mTestHelper.await(lock)
|
||||||
|
|
||||||
|
bobTimeline.getTimelineEventAtIndex(0)?.root?.let {
|
||||||
|
val decryptionResult = bobSession.cryptoService().decryptEvent(it, "")
|
||||||
|
val text = (decryptionResult.clearEvent["content"] as Map<*, *>)["body"]
|
||||||
|
assertEquals("test", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,15 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto
|
package im.vector.matrix.android.internal.crypto
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import com.squareup.sqldelight.ColumnAdapter
|
||||||
|
import com.squareup.sqldelight.android.AndroidSqliteDriver
|
||||||
|
import com.squareup.sqldelight.logs.LogSqliteDriver
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
import im.vector.matrix.android.BuildConfig
|
||||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||||
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
|
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
|
||||||
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
||||||
@ -55,9 +61,9 @@ import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreRoomSessio
|
|||||||
import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
|
import im.vector.matrix.android.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
|
||||||
import im.vector.matrix.android.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
|
import im.vector.matrix.android.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
|
||||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
|
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration
|
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreMigration
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
||||||
|
import im.vector.matrix.android.internal.crypto.store.db.SqlCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice
|
import im.vector.matrix.android.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.DefaultDeleteDeviceTask
|
||||||
@ -87,12 +93,13 @@ import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask
|
|||||||
import im.vector.matrix.android.internal.crypto.tasks.UploadSignaturesTask
|
import im.vector.matrix.android.internal.crypto.tasks.UploadSignaturesTask
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask
|
import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask
|
||||||
import im.vector.matrix.android.internal.database.RealmKeysUtils
|
import im.vector.matrix.android.internal.database.RealmKeysUtils
|
||||||
import im.vector.matrix.android.internal.di.CryptoDatabase
|
|
||||||
import im.vector.matrix.android.internal.di.SessionFilesDirectory
|
import im.vector.matrix.android.internal.di.SessionFilesDirectory
|
||||||
import im.vector.matrix.android.internal.di.UserMd5
|
import im.vector.matrix.android.internal.di.UserMd5
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
|
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
|
||||||
import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask
|
import im.vector.matrix.android.internal.session.cache.RealmClearCacheTask
|
||||||
|
import im.vector.matrix.sqldelight.crypto.CrossSigningInfoEntity
|
||||||
|
import im.vector.matrix.sqldelight.crypto.CryptoDatabase
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
@ -108,7 +115,7 @@ internal abstract class CryptoModule {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
@CryptoDatabase
|
@im.vector.matrix.android.internal.di.CryptoDatabase
|
||||||
@SessionScope
|
@SessionScope
|
||||||
fun providesRealmConfiguration(@SessionFilesDirectory directory: File,
|
fun providesRealmConfiguration(@SessionFilesDirectory directory: File,
|
||||||
@UserMd5 userMd5: String,
|
@UserMd5 userMd5: String,
|
||||||
@ -125,6 +132,31 @@ internal abstract class CryptoModule {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Provides
|
||||||
|
@SessionScope
|
||||||
|
fun providesCryptoDatabase(context: Context, @SessionFilesDirectory directory: File): CryptoDatabase {
|
||||||
|
val name = "${directory.name}-matrix-sdk-crypto.db"
|
||||||
|
val driver = if (BuildConfig.DEBUG) {
|
||||||
|
LogSqliteDriver(AndroidSqliteDriver(CryptoDatabase.Schema, context, name)) { log ->
|
||||||
|
Log.d("SQLite", log)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AndroidSqliteDriver(CryptoDatabase.Schema, context, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
val listOfStringAdapter = object : ColumnAdapter<List<String>, String> {
|
||||||
|
override fun decode(databaseValue: String) = databaseValue.split(",")
|
||||||
|
override fun encode(value: List<String>) = value.joinToString(separator = ",")
|
||||||
|
}
|
||||||
|
return CryptoDatabase(
|
||||||
|
driver = driver,
|
||||||
|
crossSigningInfoEntityAdapter = CrossSigningInfoEntity.Adapter(
|
||||||
|
usagesAdapter = listOfStringAdapter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
@SessionScope
|
@SessionScope
|
||||||
@ -134,8 +166,8 @@ internal abstract class CryptoModule {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
@CryptoDatabase
|
@im.vector.matrix.android.internal.di.CryptoDatabase
|
||||||
fun providesClearCacheTask(@CryptoDatabase
|
fun providesClearCacheTask(@im.vector.matrix.android.internal.di.CryptoDatabase
|
||||||
realmConfiguration: RealmConfiguration): ClearCacheTask {
|
realmConfiguration: RealmConfiguration): ClearCacheTask {
|
||||||
return RealmClearCacheTask(realmConfiguration)
|
return RealmClearCacheTask(realmConfiguration)
|
||||||
}
|
}
|
||||||
@ -243,7 +275,7 @@ internal abstract class CryptoModule {
|
|||||||
abstract fun bindCrossSigningService(service: DefaultCrossSigningService): CrossSigningService
|
abstract fun bindCrossSigningService(service: DefaultCrossSigningService): CrossSigningService
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindCryptoStore(store: RealmCryptoStore): IMXCryptoStore
|
abstract fun bindCryptoStore(store: SqlCryptoStore): IMXCryptoStore
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindComputeShieldTrustTask(task: DefaultComputeTrustTask): ComputeTrustTask
|
abstract fun bindComputeShieldTrustTask(task: DefaultComputeTrustTask): ComputeTrustTask
|
||||||
|
@ -69,7 +69,6 @@ import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
|||||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
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.IMXCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.store.SavedKeyBackupKeyInfo
|
import im.vector.matrix.android.internal.crypto.store.SavedKeyBackupKeyInfo
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||||
@ -1154,11 +1153,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?, hash: String?) {
|
||||||
cryptoStore.setKeysBackupData(KeysBackupDataEntity()
|
cryptoStore.setKeysBackupData(
|
||||||
.apply {
|
im.vector.matrix.android.internal.crypto.model.rest.KeysBackupData(
|
||||||
backupLastServerNumberOfKeys = count
|
backupLastServerNumberOfKeys = count,
|
||||||
backupLastServerHash = hash
|
backupLastServerHash = hash
|
||||||
}
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.internal.crypto.model.rest
|
||||||
|
|
||||||
|
internal data class KeysBackupData(val backupLastServerHash: String?, val backupLastServerNumberOfKeys: Int?)
|
@ -32,8 +32,8 @@ import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
|||||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||||
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
|
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.rest.KeysBackupData
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.model.KeysBackupDataEntity
|
|
||||||
import org.matrix.olm.OlmAccount
|
import org.matrix.olm.OlmAccount
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,14 +104,14 @@ internal interface IMXCryptoStore {
|
|||||||
/**
|
/**
|
||||||
* Get the current keys backup local data
|
* Get the current keys backup local data
|
||||||
*/
|
*/
|
||||||
fun getKeysBackupData(): KeysBackupDataEntity?
|
fun getKeysBackupData(): KeysBackupData?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the keys backup local data
|
* Set the keys backup local data
|
||||||
*
|
*
|
||||||
* @param keysBackupData the keys backup local data, or null to erase data
|
* @param keysBackupData the keys backup local data, or null to erase data
|
||||||
*/
|
*/
|
||||||
fun setKeysBackupData(keysBackupData: KeysBackupDataEntity?)
|
fun setKeysBackupData(keysBackupData: KeysBackupData?)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the devices statuses map (userId -> tracking status)
|
* @return the devices statuses map (userId -> tracking status)
|
||||||
|
@ -41,6 +41,7 @@ import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
|||||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
import im.vector.matrix.android.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||||
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
|
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.rest.KeysBackupData
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
import im.vector.matrix.android.internal.crypto.model.toEntity
|
import im.vector.matrix.android.internal.crypto.model.toEntity
|
||||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||||
@ -705,13 +706,18 @@ internal class RealmCryptoStore @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getKeysBackupData(): KeysBackupDataEntity? {
|
override fun getKeysBackupData(): KeysBackupData? {
|
||||||
return doRealmQueryAndCopy(realmConfiguration) {
|
return doRealmQueryAndCopy(realmConfiguration) {
|
||||||
it.where<KeysBackupDataEntity>().findFirst()
|
it.where<KeysBackupDataEntity>().findFirst()
|
||||||
|
}?.let { entity ->
|
||||||
|
return KeysBackupData(
|
||||||
|
backupLastServerHash = entity.backupLastServerHash,
|
||||||
|
backupLastServerNumberOfKeys = entity.backupLastServerNumberOfKeys
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setKeysBackupData(keysBackupData: KeysBackupDataEntity?) {
|
override fun setKeysBackupData(keysBackupData: KeysBackupData?) {
|
||||||
doRealmTransaction(realmConfiguration) {
|
doRealmTransaction(realmConfiguration) {
|
||||||
if (keysBackupData == null) {
|
if (keysBackupData == null) {
|
||||||
// Clear the table
|
// Clear the table
|
||||||
@ -720,7 +726,10 @@ internal class RealmCryptoStore @Inject constructor(
|
|||||||
.deleteAllFromRealm()
|
.deleteAllFromRealm()
|
||||||
} else {
|
} else {
|
||||||
// Only one object
|
// Only one object
|
||||||
it.copyToRealmOrUpdate(keysBackupData)
|
it.copyToRealmOrUpdate(it.createObject(KeysBackupDataEntity::class.java).apply {
|
||||||
|
backupLastServerHash = keysBackupData.backupLastServerHash
|
||||||
|
backupLastServerNumberOfKeys = keysBackupData.backupLastServerNumberOfKeys
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.internal.crypto.store.db
|
||||||
|
|
||||||
|
import com.squareup.moshi.JsonAdapter
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import com.squareup.moshi.Types
|
||||||
|
import im.vector.matrix.android.api.extensions.tryThis
|
||||||
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
|
import im.vector.matrix.android.internal.crypto.GossipRequestType
|
||||||
|
import im.vector.matrix.android.internal.crypto.GossipingRequestState
|
||||||
|
import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
|
||||||
|
import im.vector.matrix.android.internal.crypto.IncomingSecretShareRequest
|
||||||
|
import im.vector.matrix.android.internal.crypto.IncomingShareRequestCommon
|
||||||
|
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequest
|
||||||
|
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestState
|
||||||
|
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequest
|
||||||
|
import im.vector.matrix.android.internal.crypto.OutgoingSecretRequest
|
||||||
|
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
|
import im.vector.matrix.android.internal.di.SerializeNulls
|
||||||
|
import im.vector.matrix.sqldelight.crypto.CrossSigningInfoEntity
|
||||||
|
import im.vector.matrix.sqldelight.crypto.DeviceInfoEntity
|
||||||
|
import im.vector.matrix.sqldelight.crypto.GetByUserId
|
||||||
|
import im.vector.matrix.sqldelight.crypto.IncomingGossipingRequestEntity
|
||||||
|
import im.vector.matrix.sqldelight.crypto.OutgoingGossipingRequestEntity
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
object SqliteCryptoMapper {
|
||||||
|
|
||||||
|
private val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build()
|
||||||
|
private val listMigrationAdapter = moshi.adapter<List<String>>(Types.newParameterizedType(
|
||||||
|
List::class.java,
|
||||||
|
String::class.java,
|
||||||
|
Any::class.java
|
||||||
|
))
|
||||||
|
private val mapMigrationAdapter = moshi.adapter<JsonDict>(Types.newParameterizedType(
|
||||||
|
Map::class.java,
|
||||||
|
String::class.java,
|
||||||
|
Any::class.java
|
||||||
|
))
|
||||||
|
private val mapOfStringMigrationAdapter = moshi.adapter<Map<String, Map<String, String>>>(Types.newParameterizedType(
|
||||||
|
Map::class.java,
|
||||||
|
String::class.java,
|
||||||
|
Any::class.java
|
||||||
|
))
|
||||||
|
private val recipientsDataMapper: JsonAdapter<Map<String, List<String>>> =
|
||||||
|
MoshiProvider
|
||||||
|
.providesMoshi()
|
||||||
|
.adapter<Map<String, List<String>>>(
|
||||||
|
Types.newParameterizedType(Map::class.java, String::class.java, List::class.java)
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun mapToEntity(deviceInfo: CryptoDeviceInfo): DeviceInfoEntity {
|
||||||
|
return DeviceInfoEntity.Impl(
|
||||||
|
user_id = deviceInfo.userId,
|
||||||
|
device_id = deviceInfo.deviceId,
|
||||||
|
identity_key = deviceInfo.identityKey(),
|
||||||
|
algorithm_list_json = listMigrationAdapter.toJson(deviceInfo.algorithms),
|
||||||
|
keys_map_json = mapMigrationAdapter.toJson(deviceInfo.keys),
|
||||||
|
signature_map_json = mapMigrationAdapter.toJson(deviceInfo.signatures),
|
||||||
|
is_blocked = deviceInfo.isBlocked,
|
||||||
|
locally_verified = deviceInfo.trustLevel?.locallyVerified == true,
|
||||||
|
cross_signed_verified = deviceInfo.trustLevel?.crossSigningVerified == true,
|
||||||
|
unsigned_map_json = mapMigrationAdapter.toJson(deviceInfo.unsigned)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun mapToModel(deviceInfoEntity: DeviceInfoEntity): CryptoDeviceInfo {
|
||||||
|
return CryptoDeviceInfo(
|
||||||
|
deviceId = deviceInfoEntity.device_id,
|
||||||
|
userId = deviceInfoEntity.user_id,
|
||||||
|
algorithms = deviceInfoEntity.algorithm_list_json?.let {
|
||||||
|
try {
|
||||||
|
listMigrationAdapter.fromJson(it)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.e(failure)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keys = deviceInfoEntity.keys_map_json?.let {
|
||||||
|
try {
|
||||||
|
moshi.adapter<Map<String, String>>(Types.newParameterizedType(
|
||||||
|
Map::class.java,
|
||||||
|
String::class.java,
|
||||||
|
Any::class.java
|
||||||
|
)).fromJson(it)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.e(failure)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
signatures = deviceInfoEntity.signature_map_json?.let {
|
||||||
|
try {
|
||||||
|
mapOfStringMigrationAdapter.fromJson(it)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.e(failure)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
unsigned = deviceInfoEntity.unsigned_map_json?.let {
|
||||||
|
try {
|
||||||
|
mapMigrationAdapter.fromJson(it)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.e(failure)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trustLevel = DeviceTrustLevel(deviceInfoEntity.cross_signed_verified, deviceInfoEntity.locally_verified),
|
||||||
|
isBlocked = deviceInfoEntity.is_blocked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun mapToModel(crossSigningInfoEntity: GetByUserId): CryptoCrossSigningKey {
|
||||||
|
val pubKey = crossSigningInfoEntity.public_key_base64 ?: ""
|
||||||
|
return CryptoCrossSigningKey(
|
||||||
|
userId = crossSigningInfoEntity.user_id,
|
||||||
|
signatures = crossSigningInfoEntity.signatures?.let { deserializeSignaturesFromSqlite(it) },
|
||||||
|
trustLevel = DeviceTrustLevel(
|
||||||
|
crossSigningInfoEntity.cross_signed_verified,
|
||||||
|
crossSigningInfoEntity.locally_verified
|
||||||
|
),
|
||||||
|
keys = mapOf("ed25519:$pubKey" to pubKey),
|
||||||
|
usages = crossSigningInfoEntity.usages
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun mapToEntity(cryptoCrossSigningKey: CryptoCrossSigningKey): CrossSigningInfoEntity {
|
||||||
|
return CrossSigningInfoEntity.Impl(
|
||||||
|
user_id = cryptoCrossSigningKey.userId,
|
||||||
|
signatures = serializeSignaturesForSqlite(cryptoCrossSigningKey.signatures),
|
||||||
|
public_key_base64 = cryptoCrossSigningKey.unpaddedBase64PublicKey,
|
||||||
|
usages = cryptoCrossSigningKey.usages ?: emptyList(),
|
||||||
|
locally_verified = false,
|
||||||
|
cross_signed_verified = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serializeSignaturesForSqlite(signatures: Map<String, Map<String, String>>?): String {
|
||||||
|
return mapMigrationAdapter.toJson(signatures)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserializeSignaturesFromSqlite(signatures: String):Map<String, Map<String, String>>? {
|
||||||
|
return try {
|
||||||
|
mapOfStringMigrationAdapter.fromJson(signatures)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.e(failure)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toOutgoingGossipingRequest(entity: OutgoingGossipingRequestEntity): OutgoingGossipingRequest {
|
||||||
|
return when (entity.type) {
|
||||||
|
GossipRequestType.KEY.name -> {
|
||||||
|
OutgoingRoomKeyRequest(
|
||||||
|
requestBody = getRequestedKeyInfo(entity.type, entity.requested_info),
|
||||||
|
recipients = getRecipientsMap(entity) ?: emptyMap(),
|
||||||
|
requestId = entity.request_id,
|
||||||
|
state = tryThis { OutgoingGossipingRequestState.valueOf(entity.requested_info!!) }
|
||||||
|
?: OutgoingGossipingRequestState.UNSENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
GossipRequestType.SECRET.name -> {
|
||||||
|
OutgoingSecretRequest(
|
||||||
|
secretName = getRequestedSecretName(entity.type, entity.requested_info),
|
||||||
|
recipients = getRecipientsMap(entity) ?: emptyMap(),
|
||||||
|
requestId = entity.request_id,
|
||||||
|
state = tryThis { OutgoingGossipingRequestState.valueOf(entity.requested_info!!) }
|
||||||
|
?: OutgoingGossipingRequestState.UNSENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> OutgoingRoomKeyRequest(
|
||||||
|
requestBody = getRequestedKeyInfo(entity.type, entity.requested_info),
|
||||||
|
recipients = getRecipientsMap(entity) ?: emptyMap(),
|
||||||
|
requestId = entity.request_id,
|
||||||
|
state = OutgoingGossipingRequestState.UNSENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toIncomingGossipingRequest(entity: IncomingGossipingRequestEntity): IncomingShareRequestCommon {
|
||||||
|
return when (GossipRequestType.valueOf(entity.type)) {
|
||||||
|
GossipRequestType.KEY -> {
|
||||||
|
IncomingRoomKeyRequest(
|
||||||
|
requestBody = getRequestedKeyInfo(entity.type, entity.requested_info_str),
|
||||||
|
deviceId = entity.other_device_id,
|
||||||
|
userId = entity.other_user_id,
|
||||||
|
requestId = entity.request_id,
|
||||||
|
state = entity.request_state?.let { GossipingRequestState.valueOf(it) }
|
||||||
|
?: GossipingRequestState.NONE,
|
||||||
|
localCreationTimestamp = entity.local_creation_timestamp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
GossipRequestType.SECRET -> {
|
||||||
|
IncomingSecretShareRequest(
|
||||||
|
secretName = getRequestedSecretName(entity.type, entity.requested_info_str),
|
||||||
|
deviceId = entity.other_device_id,
|
||||||
|
userId = entity.other_user_id,
|
||||||
|
requestId = entity.request_id,
|
||||||
|
localCreationTimestamp = entity.local_creation_timestamp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRecipientsMap(entity: OutgoingGossipingRequestEntity): Map<String, List<String>>? {
|
||||||
|
return entity.recipients_data?.let { recipientsDataMapper.fromJson(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRecipientsData(recipients: Map<String, List<String>>): String? {
|
||||||
|
return recipientsDataMapper.toJson(recipients)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRequestedKeyInfo(type: String, requestedInfoStr: String?): RoomKeyRequestBody? {
|
||||||
|
return if (type == GossipRequestType.KEY.name) {
|
||||||
|
RoomKeyRequestBody.fromJson(requestedInfoStr)
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRequestedSecretName(type: String, requestedInfoStr: String?): String? {
|
||||||
|
return if (type == GossipRequestType.SECRET.name) {
|
||||||
|
requestedInfoStr
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package im.vector.matrix.android.internal.crypto.store.db
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
|
import im.vector.matrix.android.internal.util.CompatUtil
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.io.ObjectInputStream
|
||||||
|
import java.io.ObjectOutputStream
|
||||||
|
import java.util.zip.GZIPInputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize any Serializable object, zip it and convert to Base64 String
|
||||||
|
*/
|
||||||
|
fun serializeForSqlite(o: Any?): String? {
|
||||||
|
if (o == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val baos = ByteArrayOutputStream()
|
||||||
|
val gzis = CompatUtil.createGzipOutputStream(baos)
|
||||||
|
val out = ObjectOutputStream(gzis)
|
||||||
|
|
||||||
|
out.writeObject(o)
|
||||||
|
out.close()
|
||||||
|
|
||||||
|
return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the opposite of serializeForSqlite.
|
||||||
|
*/
|
||||||
|
fun <T> deserializeFromSqlite(string: String?): T? {
|
||||||
|
if (string == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val decodedB64 = Base64.decode(string.toByteArray(), Base64.DEFAULT)
|
||||||
|
|
||||||
|
val bais = ByteArrayInputStream(decodedB64)
|
||||||
|
val gzis = GZIPInputStream(bais)
|
||||||
|
val ois = ObjectInputStream(gzis)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val result = ois.readObject() as T
|
||||||
|
|
||||||
|
ois.close()
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
import kotlin.collections.List;
|
||||||
|
|
||||||
|
CREATE TABLE crossSigningInfoEntity (
|
||||||
|
user_id TEXT NOT NULL,
|
||||||
|
usages TEXT AS List<String> NOT NULL,
|
||||||
|
public_key_base64 TEXT,
|
||||||
|
signatures TEXT,
|
||||||
|
cross_signed_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
locally_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
PRIMARY KEY(user_id, usages)
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO crossSigningInfoEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM crossSigningInfoEntity;
|
||||||
|
|
||||||
|
getByUserId:
|
||||||
|
SELECT rowid AS _id,
|
||||||
|
user_id,
|
||||||
|
usages,
|
||||||
|
public_key_base64,
|
||||||
|
signatures,
|
||||||
|
cross_signed_verified,
|
||||||
|
locally_verified
|
||||||
|
FROM crossSigningInfoEntity
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
updateLocallyVerifiedWithRowId:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET locally_verified = :locallyVerified
|
||||||
|
WHERE rowid = :rowId;
|
||||||
|
|
||||||
|
updateLocallyVerified:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET locally_verified = :locallyVerified
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
updateCrossSignedVerified:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET cross_signed_verified = :crossSignedVerified
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
updateVerified:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET locally_verified = :locallyVerified,
|
||||||
|
cross_signed_verified = :crossSignedVerified
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
updateSignatures:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET signatures = :signatures
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
updateSignaturesWithRowId:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET signatures = :signatures
|
||||||
|
WHERE rowid = :rowId;
|
||||||
|
|
||||||
|
updateUsages:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET usages = :usages
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
updateUsagesWithRowId:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET usages = :usages
|
||||||
|
WHERE rowid = :rowId;
|
||||||
|
|
||||||
|
clearOtherUserTrust:
|
||||||
|
UPDATE crossSigningInfoEntity
|
||||||
|
SET locally_verified = 0,
|
||||||
|
cross_signed_verified = 0
|
||||||
|
WHERE user_id != :userId;
|
||||||
|
|
||||||
|
deleteByUserId:
|
||||||
|
DELETE FROM crossSigningInfoEntity
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM crossSigningInfoEntity;
|
@ -0,0 +1,66 @@
|
|||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
CREATE TABLE cryptoMetadataEntity (
|
||||||
|
user_id TEXT PRIMARY KEY NOT NULL,
|
||||||
|
device_id TEXT,
|
||||||
|
olm_account_data TEXT,
|
||||||
|
device_sync_token TEXT,
|
||||||
|
global_blacklist_unverified_devices INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
backup_version TEXT,
|
||||||
|
x_sign_master_private_key TEXT,
|
||||||
|
x_sign_user_private_key TEXT,
|
||||||
|
x_sign_self_signed_private_key TEXT,
|
||||||
|
key_backup_recovery_key TEXT,
|
||||||
|
key_backup_recovery_key_version TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO cryptoMetadataEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM cryptoMetadataEntity;
|
||||||
|
|
||||||
|
getByUserId:
|
||||||
|
SELECT * FROM cryptoMetadataEntity
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
count:
|
||||||
|
SELECT COUNT(*) FROM cryptoMetadataEntity;
|
||||||
|
|
||||||
|
updateOlmAccountData:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET olm_account_data = :olmAccountData;
|
||||||
|
|
||||||
|
updateGlobalBlacklistUnverifiedDevices:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET global_blacklist_unverified_devices = :globalBlacklistUnverifiedDevices;
|
||||||
|
|
||||||
|
updateKeyBackupVersion:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET backup_version = :backupVersion;
|
||||||
|
|
||||||
|
updateDeviceId:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET device_id = :deviceId;
|
||||||
|
|
||||||
|
updateKeys:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET x_sign_master_private_key = :xSignMasterPrivateKey,
|
||||||
|
x_sign_user_private_key = :xSignUserPrivateKey,
|
||||||
|
x_sign_self_signed_private_key = :xSignSelfSignedPrivateKey;
|
||||||
|
|
||||||
|
updateSelfSignedPrivateKey:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET x_sign_self_signed_private_key = :xSignSelfSignedPrivateKey;
|
||||||
|
|
||||||
|
updateUserPrivateKey:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET x_sign_user_private_key = :xSignUserPrivateKey;
|
||||||
|
|
||||||
|
updateKeyBackupRecoveryKey:
|
||||||
|
UPDATE cryptoMetadataEntity
|
||||||
|
SET key_backup_recovery_key = :keyBackupRecoveryKey,
|
||||||
|
key_backup_recovery_key_version = :keyBackupRecoveryKeyVersion;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM cryptoMetadataEntity;
|
@ -0,0 +1,50 @@
|
|||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
CREATE TABLE cryptoRoomEntity (
|
||||||
|
room_id TEXT NOT NULL PRIMARY KEY,
|
||||||
|
algorithm TEXT,
|
||||||
|
should_encrypt_for_invited_members INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
blacklist_unverified_devices INTEGER AS Boolean DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO cryptoRoomEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM cryptoRoomEntity;
|
||||||
|
|
||||||
|
getById:
|
||||||
|
SELECT * FROM cryptoRoomEntity
|
||||||
|
WHERE room_id = :roomId;
|
||||||
|
|
||||||
|
getBlacklistUnverifiedDevices:
|
||||||
|
SELECT * FROM cryptoRoomEntity
|
||||||
|
WHERE blacklist_unverified_devices = :blacklistUnverifiedDevices;
|
||||||
|
|
||||||
|
getRoomAlgorithm:
|
||||||
|
SELECT algorithm
|
||||||
|
FROM cryptoRoomEntity
|
||||||
|
WHERE room_id = :roomId;
|
||||||
|
|
||||||
|
shouldEncryptForInvitedMembers:
|
||||||
|
SELECT should_encrypt_for_invited_members
|
||||||
|
FROM cryptoRoomEntity
|
||||||
|
WHERE room_id = :roomId;
|
||||||
|
|
||||||
|
updateShouldEncryptForInvitedMembers:
|
||||||
|
UPDATE cryptoRoomEntity
|
||||||
|
SET should_encrypt_for_invited_members = :shouldEncryptForInvitedMembers
|
||||||
|
WHERE room_id = :roomId;
|
||||||
|
|
||||||
|
updateBlacklistUnverifiedDevices:
|
||||||
|
UPDATE cryptoRoomEntity
|
||||||
|
SET blacklist_unverified_devices = :blacklistUnverifiedDevices
|
||||||
|
WHERE room_id = :roomId;
|
||||||
|
|
||||||
|
updateRoomAlgorithm:
|
||||||
|
UPDATE cryptoRoomEntity
|
||||||
|
SET algorithm = :algorithm
|
||||||
|
WHERE room_id = :roomId;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM cryptoRoomEntity;
|
@ -0,0 +1,23 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
CREATE TABLE cryptoUserEntity (
|
||||||
|
user_id TEXT NOT NULL PRIMARY KEY,
|
||||||
|
device_tracking_status INTEGER AS Integer DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO cryptoUserEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM cryptoUserEntity;
|
||||||
|
|
||||||
|
getByUserId:
|
||||||
|
SELECT * FROM cryptoUserEntity
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
deleteByUserId:
|
||||||
|
DELETE FROM cryptoUserEntity
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM cryptoUserEntity;
|
@ -0,0 +1,56 @@
|
|||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
CREATE TABLE deviceInfoEntity (
|
||||||
|
user_id TEXT NOT NULL,
|
||||||
|
device_id TEXT NOT NULL,
|
||||||
|
identity_key TEXT,
|
||||||
|
is_blocked INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
algorithm_list_json TEXT,
|
||||||
|
keys_map_json TEXT,
|
||||||
|
signature_map_json TEXT,
|
||||||
|
unsigned_map_json TEXT,
|
||||||
|
cross_signed_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
locally_verified INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
PRIMARY KEY(user_id, device_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO deviceInfoEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM deviceInfoEntity;
|
||||||
|
|
||||||
|
getByUserIdAndDeviceId:
|
||||||
|
SELECT * FROM deviceInfoEntity
|
||||||
|
WHERE user_id = :userId
|
||||||
|
AND device_id = :deviceId;
|
||||||
|
|
||||||
|
getByUserId:
|
||||||
|
SELECT * FROM deviceInfoEntity
|
||||||
|
WHERE user_id = :userId;
|
||||||
|
|
||||||
|
getByIdentityKey:
|
||||||
|
SELECT * FROM deviceInfoEntity
|
||||||
|
WHERE identity_key = :identityKey;
|
||||||
|
|
||||||
|
updateLocallyVerified:
|
||||||
|
UPDATE deviceInfoEntity
|
||||||
|
SET locally_verified = :locallyVerified
|
||||||
|
WHERE user_id = :userId
|
||||||
|
AND device_id = :deviceId;
|
||||||
|
|
||||||
|
updateCrossSignedVerified:
|
||||||
|
UPDATE deviceInfoEntity
|
||||||
|
SET cross_signed_verified = :crossSignedVerified
|
||||||
|
WHERE user_id = :userId
|
||||||
|
AND device_id = :deviceId;
|
||||||
|
|
||||||
|
updateVerified:
|
||||||
|
UPDATE deviceInfoEntity
|
||||||
|
SET locally_verified = :locallyVerified,
|
||||||
|
cross_signed_verified = :crossSignedVerified
|
||||||
|
WHERE user_id = :userId
|
||||||
|
AND device_id = :deviceId;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM deviceInfoEntity;
|
@ -0,0 +1,31 @@
|
|||||||
|
import java.lang.Long;
|
||||||
|
|
||||||
|
CREATE TABLE gossipingEventEntity (
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
sender TEXT NOT NULL,
|
||||||
|
send_state TEXT,
|
||||||
|
content TEXT,
|
||||||
|
decryption_result_json TEXT,
|
||||||
|
decryption_error_code TEXT,
|
||||||
|
age_local_ts INTEGER AS Long DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX gossiping_event_type ON gossipingEventEntity(type);
|
||||||
|
CREATE INDEX gossiping_event_sender ON gossipingEventEntity(sender);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO gossipingEventEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM gossipingEventEntity;
|
||||||
|
|
||||||
|
getByType:
|
||||||
|
SELECT * FROM gossipingEventEntity
|
||||||
|
WHERE type = :type;
|
||||||
|
|
||||||
|
getBySender:
|
||||||
|
SELECT * FROM gossipingEventEntity
|
||||||
|
WHERE sender = :sender;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM gossipingEventEntity;
|
@ -0,0 +1,49 @@
|
|||||||
|
import java.lang.Long;
|
||||||
|
|
||||||
|
CREATE TABLE incomingGossipingRequestEntity (
|
||||||
|
request_id TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
other_user_id TEXT,
|
||||||
|
requested_info_str TEXT,
|
||||||
|
request_state TEXT,
|
||||||
|
other_device_id TEXT,
|
||||||
|
local_creation_timestamp INTEGER AS Long DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX incoming_gossiping_request_request_id ON incomingGossipingRequestEntity(request_id);
|
||||||
|
CREATE INDEX incoming_gossiping_request_type ON incomingGossipingRequestEntity(type);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO incomingGossipingRequestEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM incomingGossipingRequestEntity;
|
||||||
|
|
||||||
|
getByType:
|
||||||
|
SELECT * FROM incomingGossipingRequestEntity
|
||||||
|
WHERE type = :type;
|
||||||
|
|
||||||
|
getByRequestState:
|
||||||
|
SELECT * FROM incomingGossipingRequestEntity
|
||||||
|
WHERE request_state = :requestState;
|
||||||
|
|
||||||
|
getByTypeAndRequestState:
|
||||||
|
SELECT * FROM incomingGossipingRequestEntity
|
||||||
|
WHERE type = :type
|
||||||
|
AND request_state = :requestState;
|
||||||
|
|
||||||
|
getIncomingRoomKeyRequest:
|
||||||
|
SELECT * FROM incomingGossipingRequestEntity
|
||||||
|
WHERE type = :type
|
||||||
|
AND other_user_id = :otherUserId
|
||||||
|
AND other_device_id = :otherDeviceId;
|
||||||
|
|
||||||
|
updateRequestState:
|
||||||
|
UPDATE incomingGossipingRequestEntity
|
||||||
|
SET request_state = :requestState
|
||||||
|
WHERE other_user_id = :otherUserId
|
||||||
|
AND other_device_id = :otherDeviceId
|
||||||
|
AND request_id = :requestId;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM incomingGossipingRequestEntity;
|
@ -0,0 +1,14 @@
|
|||||||
|
CREATE TABLE keysBackupDataEntity (
|
||||||
|
static_id INTEGER PRIMARY KEY CHECK (static_id = 0),
|
||||||
|
backup_last_server_hash TEXT,
|
||||||
|
backup_last_server_number_of_keys INTEGER DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO keysBackupDataEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM keysBackupDataEntity;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM keysBackupDataEntity;
|
@ -0,0 +1,52 @@
|
|||||||
|
import java.lang.Boolean;
|
||||||
|
|
||||||
|
CREATE TABLE olmInboundGroupSessionEntity (
|
||||||
|
session_id TEXT NOT NULL,
|
||||||
|
sender_key TEXT NOT NULL,
|
||||||
|
olm_inbound_group_session_data TEXT,
|
||||||
|
backed_up INTEGER AS Boolean DEFAULT 0 NOT NULL,
|
||||||
|
PRIMARY KEY(session_id, sender_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO olmInboundGroupSessionEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM olmInboundGroupSessionEntity;
|
||||||
|
|
||||||
|
getBySessionIdAndSenderKey:
|
||||||
|
SELECT * FROM olmInboundGroupSessionEntity
|
||||||
|
WHERE session_id = :sessionId
|
||||||
|
AND sender_key = :senderKey;
|
||||||
|
|
||||||
|
getAllBackedUp:
|
||||||
|
SELECT * FROM olmInboundGroupSessionEntity
|
||||||
|
WHERE backed_up = :isbackedUp
|
||||||
|
LIMIT :limit;
|
||||||
|
|
||||||
|
countAll:
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM olmInboundGroupSessionEntity;
|
||||||
|
|
||||||
|
countBackedUp:
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM olmInboundGroupSessionEntity
|
||||||
|
WHERE backed_up = :backedUp;
|
||||||
|
|
||||||
|
deleteBySessionIdAndSenderKey:
|
||||||
|
DELETE FROM olmInboundGroupSessionEntity
|
||||||
|
WHERE session_id = :sessionId
|
||||||
|
AND sender_key = :senderKey;
|
||||||
|
|
||||||
|
setAllBackedUp:
|
||||||
|
UPDATE olmInboundGroupSessionEntity
|
||||||
|
SET backed_up = :isBackedUp;
|
||||||
|
|
||||||
|
setBackedUp:
|
||||||
|
UPDATE olmInboundGroupSessionEntity
|
||||||
|
SET backed_up = :isBackedUp
|
||||||
|
WHERE session_id = :sessionId
|
||||||
|
AND sender_key = :senderKey;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM olmInboundGroupSessionEntity;
|
@ -0,0 +1,34 @@
|
|||||||
|
import java.lang.Long;
|
||||||
|
|
||||||
|
CREATE TABLE olmSessionEntity (
|
||||||
|
session_id TEXT NOT NULL,
|
||||||
|
device_key TEXT NOT NULL,
|
||||||
|
olm_session_data TEXT,
|
||||||
|
last_received_message_ts INTEGER AS Long DEFAULT 0 NOT NULL,
|
||||||
|
PRIMARY KEY(session_id, device_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX olm_session_device_key ON olmSessionEntity(device_key);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO olmSessionEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM olmSessionEntity;
|
||||||
|
|
||||||
|
getBySessionIdAndDeviceKey:
|
||||||
|
SELECT * FROM olmSessionEntity
|
||||||
|
WHERE session_id = :sessionId
|
||||||
|
AND device_key = :deviceKey;
|
||||||
|
|
||||||
|
getByDeviceKey:
|
||||||
|
SELECT * FROM olmSessionEntity
|
||||||
|
WHERE device_key = :deviceKey;
|
||||||
|
|
||||||
|
getByDeviceKeyDescending:
|
||||||
|
SELECT * FROM olmSessionEntity
|
||||||
|
WHERE device_key = :deviceKey
|
||||||
|
ORDER BY last_received_message_ts DESC;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM olmSessionEntity;
|
@ -0,0 +1,37 @@
|
|||||||
|
CREATE TABLE outgoingGossipingRequestEntity (
|
||||||
|
request_id TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
recipients_data TEXT,
|
||||||
|
requested_info TEXT,
|
||||||
|
request_state TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX outgoing_gossiping_request_request_id ON outgoingGossipingRequestEntity(request_id);
|
||||||
|
CREATE INDEX outgoing_gossiping_request_type ON outgoingGossipingRequestEntity(type);
|
||||||
|
|
||||||
|
insertOrUpdate:
|
||||||
|
INSERT OR REPLACE INTO outgoingGossipingRequestEntity VALUES ?;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM outgoingGossipingRequestEntity;
|
||||||
|
|
||||||
|
getByRequestId:
|
||||||
|
SELECT * FROM outgoingGossipingRequestEntity
|
||||||
|
WHERE request_id = :requestId;
|
||||||
|
|
||||||
|
getByType:
|
||||||
|
SELECT * FROM outgoingGossipingRequestEntity
|
||||||
|
WHERE type = :type;
|
||||||
|
|
||||||
|
getByTypeAndRequestedInfo:
|
||||||
|
SELECT * FROM outgoingGossipingRequestEntity
|
||||||
|
WHERE type = :type
|
||||||
|
AND requested_info = :requestedInfo;
|
||||||
|
|
||||||
|
updateRequestState:
|
||||||
|
UPDATE outgoingGossipingRequestEntity
|
||||||
|
SET request_state = :requestState
|
||||||
|
WHERE request_id = :requestId;
|
||||||
|
|
||||||
|
deleteAll:
|
||||||
|
DELETE FROM outgoingGossipingRequestEntity;
|
@ -1,2 +1,3 @@
|
|||||||
include ':vector', ':matrix-sdk-android', ':matrix-sdk-android-rx', ':diff-match-patch', ':matrix-sdk-sqldelight'
|
include ':vector', ':matrix-sdk-android', ':matrix-sdk-android-rx', ':diff-match-patch', ':matrix-sdk-sqldelight'
|
||||||
include ':multipicker'
|
include ':multipicker'
|
||||||
|
include ':matrix-sdk-sqldelight'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user