diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index c5df78b3cc..a3369c45e8 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -859,31 +859,7 @@ internal class DefaultCryptoService @Inject constructor( cryptoCoroutineScope.launch(coroutineDispatchers.main) { runCatching { withContext(coroutineDispatchers.crypto) { - Timber.v("## CRYPTO | importRoomKeys starts") - - val t0 = System.currentTimeMillis() - val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) - val t1 = System.currentTimeMillis() - - Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms") - - val importedSessions = MoshiProvider.providesMoshi() - .adapter>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java)) - .fromJson(roomKeys) - - val t2 = System.currentTimeMillis() - - Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms") - - if (importedSessions == null) { - throw Exception("Error") - } - - megolmSessionDataImporter.handle( - megolmSessionsData = importedSessions, - fromBackup = false, - progressListener = progressListener - ) + olmMachine!!.importKeys(roomKeysAsArray, password, progressListener) } }.foldToCallback(callback) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/newCrypto.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/newCrypto.kt index a8e536bf76..76f47ecc4f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/newCrypto.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/newCrypto.kt @@ -19,26 +19,29 @@ package org.matrix.android.sdk.internal import java.io.File import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult +import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.internal.crypto.model.rest.UnsignedDeviceInfo import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.session.sync.model.DeviceListResponse import org.matrix.android.sdk.internal.session.sync.model.DeviceOneTimeKeysCountSyncResponse import org.matrix.android.sdk.internal.session.sync.model.ToDeviceSyncResponse -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.rest.UnsignedDeviceInfo -import org.matrix.android.sdk.api.session.events.model.Content import timber.log.Timber +import uniffi.olm.CryptoStoreErrorException import uniffi.olm.Device as InnerDevice import uniffi.olm.DeviceLists import uniffi.olm.Logger import uniffi.olm.OlmMachine as InnerMachine +import uniffi.olm.ProgressListener as RustProgressListener import uniffi.olm.Request import uniffi.olm.RequestType -import uniffi.olm.CryptoStoreErrorException import uniffi.olm.Sas as InnerSas import uniffi.olm.setLogger @@ -48,6 +51,16 @@ class CryptoLogger() : Logger { } } +private class CryptoProgressListener(listener: ProgressListener?) : RustProgressListener { + private val inner: ProgressListener? = listener + + override fun onProgress(progress: Int, total: Int) { + if (this.inner != null) { + this.inner.onProgress(progress, total) + } + } +} + fun setRustLogger() { setLogger(CryptoLogger() as Logger) } @@ -121,7 +134,6 @@ internal class OlmMachine(user_id: String, device_id: String, path: File) { false, null ) - } suspend fun outgoingRequests(): List = withContext(Dispatchers.IO) { @@ -185,6 +197,17 @@ internal class OlmMachine(user_id: String, device_id: String, path: File) { inner.exportKeys(passphrase, rounds).toByteArray() } + @Throws(CryptoStoreErrorException::class) + suspend fun importKeys(keys: ByteArray, passphrase: String, listener: ProgressListener?): ImportRoomKeysResult = withContext(Dispatchers.IO) { + var decodedKeys = keys.toString() + + var rustListener = CryptoProgressListener(listener) + + var result = inner.importKeys(decodedKeys, passphrase, rustListener) + + ImportRoomKeysResult(result.total, result.imported) + } + @Throws(MXCryptoError::class) suspend fun decryptRoomEvent(event: Event): MXEventDecryptionResult = withContext(Dispatchers.IO) { val adapter = MoshiProvider.providesMoshi().adapter(Event::class.java) diff --git a/rust-sdk/src/lib.rs b/rust-sdk/src/lib.rs index 9ca691778e..2f22012c78 100644 --- a/rust-sdk/src/lib.rs +++ b/rust-sdk/src/lib.rs @@ -4,6 +4,12 @@ mod machine; pub use error::{CryptoStoreError, DecryptionError, MachineCreationError}; pub use logger::{set_logger, Logger}; -pub use machine::{DecryptedEvent, Device, DeviceLists, OlmMachine, Request, RequestType, Sas}; +pub use machine::{ + DecryptedEvent, Device, DeviceLists, KeysImportResult, OlmMachine, Request, RequestType, Sas, +}; + +pub trait ProgressListener { + fn on_progress(&self, progress: i32, total: i32); +} include!(concat!(env!("OUT_DIR"), "/olm.uniffi.rs")); diff --git a/rust-sdk/src/machine.rs b/rust-sdk/src/machine.rs index 8baebb3db3..d7dc13ca1f 100644 --- a/rust-sdk/src/machine.rs +++ b/rust-sdk/src/machine.rs @@ -1,6 +1,7 @@ use std::{ collections::{BTreeMap, HashMap}, convert::{TryFrom, TryInto}, + io::Cursor, }; use http::Response; @@ -25,11 +26,12 @@ use matrix_sdk_common::{ }; use matrix_sdk_crypto::{ - encrypt_key_export, EncryptionSettings, IncomingResponse, OlmMachine as InnerMachine, - OutgoingRequest, ToDeviceRequest, + decrypt_key_export, encrypt_key_export, EncryptionSettings, IncomingResponse, + OlmMachine as InnerMachine, OutgoingRequest, ToDeviceRequest, }; use crate::error::{CryptoStoreError, DecryptionError, MachineCreationError}; +use crate::ProgressListener; pub struct OlmMachine { inner: InnerMachine, @@ -65,6 +67,11 @@ impl Into for DeviceLists { } } +pub struct KeysImportResult { + pub total: i32, + pub imported: i32, +} + enum OwnedResponse { KeysClaim(KeysClaimResponse), KeysUpload(KeysUploadResponse), @@ -428,6 +435,24 @@ impl OlmMachine { Ok(encrypted) } + pub fn import_keys( + &self, + keys: &str, + passphrase: &str, + _: Box, + ) -> Result { + let keys = Cursor::new(keys); + let keys = decrypt_key_export(keys, passphrase).unwrap(); + + // TODO use the progress listener + let result = self.runtime.block_on(self.inner.import_keys(keys))?; + + Ok(KeysImportResult { + total: result.1 as i32, + imported: result.0 as i32, + }) + } + pub fn decrypt_room_event( &self, event: &str, diff --git a/rust-sdk/src/olm.udl b/rust-sdk/src/olm.udl index 367de7cec3..7c61cdfb60 100644 --- a/rust-sdk/src/olm.udl +++ b/rust-sdk/src/olm.udl @@ -6,6 +6,10 @@ callback interface Logger { void log(string log_line); }; +callback interface ProgressListener { + void on_progress(i32 progress, i32 total); +}; + [Error] enum MachineCreationError { "Identifier", @@ -31,6 +35,11 @@ dictionary DeviceLists { sequence left; }; +dictionary KeysImportResult { + i32 total; + i32 imported; +}; + dictionary DecryptedEvent { string clear_event; string sender_curve25519_key; @@ -106,4 +115,10 @@ interface OlmMachine { [Throws=CryptoStoreError] string export_keys([ByRef] string passphrase, i32 rounds); + [Throws=CryptoStoreError] + KeysImportResult import_keys( + [ByRef] string keys, + [ByRef] string passphrase, + ProgressListener progress_listener + ); };