matrix-sdk: Initial import of the rust-sdk crypto layer.
This commit is contained in:
parent
fa710ff601
commit
de5a02b02a
|
@ -90,6 +90,20 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
android.libraryVariants.all { variant ->
|
||||
def t = tasks.register("generate${variant.name.capitalize()}UniffiBindings", Exec) {
|
||||
// Runs the bindings generation, note that you must have uniffi-bindgen installed
|
||||
// and in your PATH environment variable
|
||||
commandLine 'uniffi-bindgen', 'generate', '../rust-sdk/src/olm.udl',
|
||||
'--language', 'kotlin',
|
||||
'--out-dir', "${buildDir}/generated/source/uniffi/${variant.name}/java"
|
||||
}
|
||||
|
||||
variant.javaCompileProvider.get().dependsOn(t)
|
||||
def sourceSet = variant.sourceSets.find { it.name == variant.name }
|
||||
sourceSet.java.srcDir new File(buildDir, "generated/source/uniffi/${variant.name}/java")
|
||||
}
|
||||
|
||||
static def gitRevision() {
|
||||
def cmd = "git rev-parse --short=8 HEAD"
|
||||
return cmd.execute().text.trim()
|
||||
|
@ -116,6 +130,8 @@ dependencies {
|
|||
def work_version = '2.4.0'
|
||||
def retrofit_version = '2.6.2'
|
||||
|
||||
implementation 'net.java.dev.jna:jna:5.6.0@aar'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.matrix.android.sdk.api.session.room.model.Membership
|
|||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.internal.OlmMachine
|
||||
import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter
|
||||
import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting
|
||||
|
@ -362,6 +363,14 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
return
|
||||
}
|
||||
isStarting.set(true)
|
||||
try {
|
||||
val dataDir = "/data/data/im.vector.app.debug/files"
|
||||
val olmMachine = OlmMachine("@example:localhost", "DEVICEID", dataDir)
|
||||
Timber.v("HELLLO WORLD STARTING CRYPTO ${olmMachine.identityKeys()}")
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.v("HELLLO WORLD FAILED CRYPTO $throwable")
|
||||
}
|
||||
Timber.v("HELLLO WORLD STARTING CRYPTO")
|
||||
|
||||
// Open the store
|
||||
cryptoStore.open()
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 org.matrix.android.sdk.internal
|
||||
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
import uniffi.olm.OlmMachine as InnerMachine
|
||||
import uniffi.olm.Device as InnerDevice
|
||||
import uniffi.olm.Sas as InnerSas
|
||||
|
||||
class Device(inner: InnerDevice, machine: InnerMachine) {
|
||||
private val machine: InnerMachine = machine
|
||||
private val inner: InnerDevice = inner
|
||||
|
||||
fun userId(): String {
|
||||
return this.inner.userId
|
||||
}
|
||||
|
||||
fun deviceId(): String {
|
||||
return this.inner.deviceId
|
||||
}
|
||||
|
||||
fun keys(): Map<String, String> {
|
||||
return this.inner.keys
|
||||
}
|
||||
|
||||
fun startVerification(): InnerSas {
|
||||
return this.machine.startVerification(this.inner)
|
||||
}
|
||||
}
|
||||
|
||||
class OlmMachine(user_id: String, device_id: String, path: String) {
|
||||
private val inner: InnerMachine = InnerMachine(user_id, device_id, path)
|
||||
|
||||
fun userId(): String {
|
||||
return this.inner.userId()
|
||||
}
|
||||
|
||||
fun deviceId(): String {
|
||||
return this.inner.deviceId()
|
||||
}
|
||||
|
||||
fun identityKeys(): Map<String, String> {
|
||||
return this.inner.identityKeys()
|
||||
}
|
||||
|
||||
suspend fun slowUserId(): String = withContext(Dispatchers.Default) {
|
||||
inner.slowUserId()
|
||||
}
|
||||
|
||||
suspend fun getDevice(user_id: String, device_id: String): Device? = withContext(Dispatchers.IO) {
|
||||
when (val device: InnerDevice? = inner.getDevice(user_id, device_id)) {
|
||||
null -> null
|
||||
else -> Device(device, inner)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "matrix-crypto-bindings"
|
||||
version = "0.1.0"
|
||||
authors = ["Damir Jelić <poljar@termina.org.uk>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "matrix_crypto"
|
||||
|
||||
[dependencies]
|
||||
matrix-sdk-crypto = { git = "https://github.com/matrix-org/matrix-rust-sdk/", features = ["sled_cryptostore"] }
|
||||
matrix-sdk-common = { git = "https://github.com/matrix-org/matrix-rust-sdk/"}
|
||||
futures = { version = "0.3.12", default_features = false, features = ["executor"] }
|
||||
tokio = { version = "1.1.1", default_features = false, features = ["rt-multi-thread", "time"] }
|
||||
serde_json = "1.0.61"
|
||||
thiserror = "1.0.23"
|
||||
http = "0.2.3"
|
||||
uniffi = "0.7.0"
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = "0.7.0"
|
||||
|
||||
[patch.crates-io]
|
||||
olm-sys = { git = "https://gitlab.gnome.org/poljar/olm-sys/", branch = "android-cross" }
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/olm.udl").unwrap();
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
use std::{collections::HashMap, convert::TryFrom, time::Duration};
|
||||
|
||||
use futures::{
|
||||
executor::block_on,
|
||||
future::{abortable, AbortHandle, Aborted},
|
||||
Future,
|
||||
};
|
||||
use http::Response;
|
||||
use tokio::{runtime::Runtime, time::sleep};
|
||||
|
||||
use matrix_sdk_common::{
|
||||
api::r0::sync::sync_events::Response as SyncResponse,
|
||||
api::r0::to_device::send_event_to_device::METADATA,
|
||||
identifiers::{Error as RumaIdentifierError, UserId},
|
||||
};
|
||||
use matrix_sdk_crypto::{
|
||||
store::CryptoStoreError as InnerStoreError, OlmMachine as InnerMachine, ToDeviceRequest,
|
||||
};
|
||||
|
||||
pub struct OlmMachine {
|
||||
inner: InnerMachine,
|
||||
runtime: Runtime,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MachineCreationError {
|
||||
#[error(transparent)]
|
||||
Identifier(#[from] RumaIdentifierError),
|
||||
#[error(transparent)]
|
||||
CryptoStore(#[from] InnerStoreError),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CryptoStoreError {
|
||||
#[error(transparent)]
|
||||
CryptoStore(#[from] InnerStoreError),
|
||||
}
|
||||
|
||||
pub enum RequestType {
|
||||
KeysQuery,
|
||||
KeysUpload,
|
||||
ToDevice,
|
||||
}
|
||||
|
||||
pub struct Device {
|
||||
pub user_id: String,
|
||||
pub device_id: String,
|
||||
pub keys: HashMap<String, String>,
|
||||
}
|
||||
|
||||
pub struct Sas {
|
||||
pub other_user_id: String,
|
||||
pub other_device_id: String,
|
||||
pub flow_id: String,
|
||||
pub request: Request,
|
||||
}
|
||||
|
||||
pub struct Request {
|
||||
pub request_id: String,
|
||||
pub request_type: RequestType,
|
||||
pub request_body: String,
|
||||
}
|
||||
|
||||
impl From<ToDeviceRequest> for Request {
|
||||
fn from(r: ToDeviceRequest) -> Self {
|
||||
Request {
|
||||
request_id: r.txn_id_string(),
|
||||
request_type: RequestType::ToDevice,
|
||||
request_body: serde_json::to_string(&r.messages).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn response_from_string(body: &str) -> Response<Vec<u8>> {
|
||||
Response::builder()
|
||||
.status(200)
|
||||
.body(body.as_bytes().to_vec())
|
||||
.expect("Can't create HTTP response")
|
||||
}
|
||||
|
||||
impl OlmMachine {
|
||||
pub fn new(user_id: &str, device_id: &str, path: &str) -> Result<Self, MachineCreationError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
let device_id = device_id.into();
|
||||
|
||||
Ok(OlmMachine {
|
||||
inner: block_on(InnerMachine::new_with_default_store(
|
||||
&user_id,
|
||||
device_id,
|
||||
path,
|
||||
Some("DEFAULT_PASSPHRASE"),
|
||||
))?,
|
||||
runtime: Runtime::new().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn user_id(&self) -> String {
|
||||
self.inner.user_id().to_string()
|
||||
}
|
||||
|
||||
pub fn device_id(&self) -> String {
|
||||
self.inner.device_id().to_string()
|
||||
}
|
||||
|
||||
pub fn get_device(&self, user_id: &str, device_id: &str) -> Option<Device> {
|
||||
let user_id = UserId::try_from(user_id).unwrap();
|
||||
|
||||
block_on(self.inner.get_device(&user_id, device_id.into()))
|
||||
.unwrap()
|
||||
.map(|d| Device {
|
||||
user_id: d.user_id().to_string(),
|
||||
device_id: d.device_id().to_string(),
|
||||
keys: d
|
||||
.keys()
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_user_devices(&self, user_id: &str) -> Vec<Device> {
|
||||
let user_id = UserId::try_from(user_id).unwrap();
|
||||
block_on(self.inner.get_user_devices(&user_id))
|
||||
.unwrap()
|
||||
.devices()
|
||||
.map(|d| Device {
|
||||
user_id: d.user_id().to_string(),
|
||||
device_id: d.device_id().to_string(),
|
||||
keys: d
|
||||
.keys()
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn identity_keys(&self) -> HashMap<String, String> {
|
||||
self.inner
|
||||
.identity_keys()
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_owned(), v.to_owned()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn slow_user_id(&self) -> String {
|
||||
let machine = self.inner.clone();
|
||||
|
||||
self.runtime.block_on(async {
|
||||
sleep(Duration::from_secs(10)).await;
|
||||
machine.user_id().to_string()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn start_verification(&self, device: &Device) -> Result<Sas, CryptoStoreError> {
|
||||
let user_id = UserId::try_from(device.user_id.clone()).unwrap();
|
||||
let device_id = device.device_id.as_str().into();
|
||||
let device = block_on(self.inner.get_device(&user_id, device_id))?.unwrap();
|
||||
|
||||
let (sas, request) = block_on(device.start_verification())?;
|
||||
|
||||
Ok(Sas {
|
||||
other_user_id: sas.other_user_id().to_string(),
|
||||
other_device_id: sas.other_device_id().to_string(),
|
||||
flow_id: sas.flow_id().as_str().to_owned(),
|
||||
request: request.into(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn receive_sync_response(&self, response: &str) {
|
||||
let response = response_from_string(response);
|
||||
let mut response = SyncResponse::try_from(response).expect("Can't parse response");
|
||||
|
||||
block_on(self.inner.receive_sync_response(&mut response)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/olm.uniffi.rs"));
|
|
@ -0,0 +1,56 @@
|
|||
namespace olm {};
|
||||
|
||||
[Error]
|
||||
enum MachineCreationError {
|
||||
"Identifier",
|
||||
"CryptoStore",
|
||||
};
|
||||
|
||||
[Error]
|
||||
enum CryptoStoreError {
|
||||
"CryptoStore",
|
||||
};
|
||||
|
||||
dictionary Device {
|
||||
string user_id;
|
||||
string device_id;
|
||||
record<DOMString, string> keys;
|
||||
};
|
||||
|
||||
dictionary Sas {
|
||||
string other_user_id;
|
||||
string other_device_id;
|
||||
string flow_id;
|
||||
Request request;
|
||||
};
|
||||
|
||||
dictionary Request {
|
||||
string request_id;
|
||||
RequestType request_type;
|
||||
string request_body;
|
||||
};
|
||||
|
||||
enum RequestType {
|
||||
"KeysQuery",
|
||||
"KeysUpload",
|
||||
"ToDevice",
|
||||
};
|
||||
|
||||
interface OlmMachine {
|
||||
[Throws=MachineCreationError]
|
||||
constructor([ByRef] string user_id, [ByRef] string device_id, [ByRef] string path);
|
||||
|
||||
void receive_sync_response([ByRef] string response);
|
||||
|
||||
record<DOMString, string> identity_keys();
|
||||
|
||||
string user_id();
|
||||
string slow_user_id();
|
||||
string device_id();
|
||||
|
||||
Device? get_device([ByRef] string user_id, [ByRef] string device_id);
|
||||
sequence<Device> get_user_devices([ByRef] string user_id);
|
||||
|
||||
[Throws=CryptoStoreError]
|
||||
Sas start_verification([ByRef] Device device);
|
||||
};
|
Loading…
Reference in New Issue