mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 19:36:08 +03:00
crypto: Export cross signing related methods from the Rust side
This commit is contained in:
parent
e2006f9dc6
commit
b012a0ff75
7 changed files with 484 additions and 43 deletions
|
@ -25,11 +25,11 @@ features = ["lax_deserialize"]
|
|||
|
||||
[dependencies.matrix-sdk-common]
|
||||
git = "https://github.com/matrix-org/matrix-rust-sdk/"
|
||||
rev = "3a8ff2f6b43f312b7582146ed712ff245ef9d5aa"
|
||||
rev = "b2ff6cb6ae3d1983a510262021cba27a1bc70d77"
|
||||
|
||||
[dependencies.matrix-sdk-crypto]
|
||||
git = "https://github.com/matrix-org/matrix-rust-sdk/"
|
||||
rev = "3a8ff2f6b43f312b7582146ed712ff245ef9d5aa"
|
||||
rev = "b2ff6cb6ae3d1983a510262021cba27a1bc70d77"
|
||||
features = ["sled_cryptostore"]
|
||||
|
||||
[dependencies.tokio]
|
||||
|
@ -38,8 +38,12 @@ default_features = false
|
|||
features = ["rt-multi-thread"]
|
||||
|
||||
[dependencies.ruma]
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
features = ["client-api"]
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = "0.12.0"
|
||||
|
||||
[patch.crates-io]
|
||||
ruma = { git = "https://github.com/matrix-org/ruma/", branch = "secrets" }
|
||||
ruma-identifiers = { git = "https://github.com/matrix-org/ruma", branch = "secrets" }
|
||||
|
|
|
@ -2,17 +2,10 @@
|
|||
|
||||
use matrix_sdk_crypto::{
|
||||
store::CryptoStoreError as InnerStoreError, KeyExportError, MegolmError, OlmError,
|
||||
SignatureError as InnerSignatureError, SecretImportError as RustSecretImportError,
|
||||
};
|
||||
use ruma::identifiers::Error as RumaIdentifierError;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MachineCreationError {
|
||||
#[error(transparent)]
|
||||
Identifier(#[from] RumaIdentifierError),
|
||||
#[error(transparent)]
|
||||
CryptoStore(#[from] InnerStoreError),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum KeyImportError {
|
||||
#[error(transparent)]
|
||||
|
@ -21,6 +14,28 @@ pub enum KeyImportError {
|
|||
CryptoStore(#[from] InnerStoreError),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum SecretImportError {
|
||||
#[error(transparent)]
|
||||
CryptoStore(#[from] InnerStoreError),
|
||||
#[error(transparent)]
|
||||
Import(#[from] RustSecretImportError),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum SignatureError {
|
||||
#[error(transparent)]
|
||||
Signature(#[from] InnerSignatureError),
|
||||
#[error(transparent)]
|
||||
Identifier(#[from] RumaIdentifierError),
|
||||
#[error(transparent)]
|
||||
CryptoStore(#[from] InnerStoreError),
|
||||
#[error("Unknown device {0} {1}")]
|
||||
UnknownDevice(String, String),
|
||||
#[error("Unknown user identity {0}")]
|
||||
UnknownUserIdentity(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CryptoStoreError {
|
||||
#[error(transparent)]
|
||||
|
|
|
@ -15,15 +15,18 @@ mod error;
|
|||
mod logger;
|
||||
mod machine;
|
||||
mod responses;
|
||||
mod users;
|
||||
mod verification;
|
||||
|
||||
pub use device::Device;
|
||||
pub use error::{CryptoStoreError, DecryptionError, KeyImportError, MachineCreationError};
|
||||
pub use error::{CryptoStoreError, DecryptionError, KeyImportError, SignatureError, SecretImportError};
|
||||
pub use logger::{set_logger, Logger};
|
||||
pub use machine::{KeyRequestPair, OlmMachine};
|
||||
pub use responses::{
|
||||
DeviceLists, KeysImportResult, OutgoingVerificationRequest, Request, RequestType,
|
||||
DeviceLists, KeysImportResult, OutgoingVerificationRequest, Request, RequestType, SignatureUploadRequest,
|
||||
BootstrapCrossSigningResult, UploadSigningKeysRequest,
|
||||
};
|
||||
pub use users::UserIdentity;
|
||||
pub use verification::{
|
||||
CancelInfo, QrCode, RequestVerificationResult, Sas, ScanResult, StartSasResult, Verification,
|
||||
VerificationRequest,
|
||||
|
@ -55,4 +58,59 @@ pub struct DecryptedEvent {
|
|||
pub forwarding_curve25519_chain: Vec<String>,
|
||||
}
|
||||
|
||||
/// Struct representing the state of our private cross signing keys, it shows
|
||||
/// which private cross signing keys we have locally stored.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CrossSigningStatus {
|
||||
/// Do we have the master key.
|
||||
pub has_master: bool,
|
||||
/// Do we have the self signing key, this one is necessary to sign our own
|
||||
/// devices.
|
||||
pub has_self_signing: bool,
|
||||
/// Do we have the user signing key, this one is necessary to sign other
|
||||
/// users.
|
||||
pub has_user_signing: bool,
|
||||
}
|
||||
|
||||
/// A struct containing private cross signing keys that can be backed up or
|
||||
/// uploaded to the secret store.
|
||||
pub struct CrossSigningKeyExport {
|
||||
/// The seed of the master key encoded as unpadded base64.
|
||||
pub master_key: Option<String>,
|
||||
/// The seed of the self signing key encoded as unpadded base64.
|
||||
pub self_signing_key: Option<String>,
|
||||
/// The seed of the user signing key encoded as unpadded base64.
|
||||
pub user_signing_key: Option<String>,
|
||||
}
|
||||
|
||||
impl From<matrix_sdk_crypto::CrossSigningKeyExport> for CrossSigningKeyExport {
|
||||
fn from(e: matrix_sdk_crypto::CrossSigningKeyExport) -> Self {
|
||||
Self {
|
||||
master_key: e.master_key.clone(),
|
||||
self_signing_key: e.self_signing_key.clone(),
|
||||
user_signing_key: e.user_signing_key.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<matrix_sdk_crypto::CrossSigningKeyExport> for CrossSigningKeyExport {
|
||||
fn into(self) -> matrix_sdk_crypto::CrossSigningKeyExport {
|
||||
matrix_sdk_crypto::CrossSigningKeyExport {
|
||||
master_key: self.master_key,
|
||||
self_signing_key: self.self_signing_key,
|
||||
user_signing_key: self.user_signing_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<matrix_sdk_crypto::CrossSigningStatus> for CrossSigningStatus {
|
||||
fn from(s: matrix_sdk_crypto::CrossSigningStatus) -> Self {
|
||||
Self {
|
||||
has_master: s.has_master,
|
||||
has_self_signing: s.has_self_signing,
|
||||
has_user_signing: s.has_user_signing,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/olm.uniffi.rs"));
|
||||
|
|
|
@ -12,6 +12,7 @@ use ruma::{
|
|||
keys::{
|
||||
claim_keys::Response as KeysClaimResponse, get_keys::Response as KeysQueryResponse,
|
||||
upload_keys::Response as KeysUploadResponse,
|
||||
upload_signatures::Response as SignatureUploadResponse,
|
||||
},
|
||||
sync::sync_events::{DeviceLists as RumaDeviceLists, ToDevice},
|
||||
to_device::send_event_to_device::Response as ToDeviceResponse,
|
||||
|
@ -31,14 +32,15 @@ use tokio::runtime::Runtime;
|
|||
use matrix_sdk_common::{deserialized_responses::AlgorithmInfo, uuid::Uuid};
|
||||
use matrix_sdk_crypto::{
|
||||
decrypt_key_export, encrypt_key_export, matrix_qrcode::QrVerificationData, EncryptionSettings,
|
||||
LocalTrust, OlmMachine as InnerMachine, Verification as RustVerification,
|
||||
LocalTrust, OlmMachine as InnerMachine, UserIdentities, Verification as RustVerification,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{CryptoStoreError, DecryptionError, MachineCreationError},
|
||||
error::{CryptoStoreError, DecryptionError, SecretImportError, SignatureError},
|
||||
responses::{response_from_string, OutgoingVerificationRequest, OwnedResponse},
|
||||
DecryptedEvent, Device, DeviceLists, KeyImportError, KeysImportResult, ProgressListener,
|
||||
QrCode, Request, RequestType, RequestVerificationResult, ScanResult, StartSasResult,
|
||||
BootstrapCrossSigningResult, CrossSigningKeyExport, CrossSigningStatus, DecryptedEvent, Device,
|
||||
DeviceLists, KeyImportError, KeysImportResult, ProgressListener, QrCode, Request, RequestType,
|
||||
RequestVerificationResult, ScanResult, SignatureUploadRequest, StartSasResult, UserIdentity,
|
||||
Verification, VerificationRequest,
|
||||
};
|
||||
|
||||
|
@ -68,7 +70,7 @@ impl OlmMachine {
|
|||
/// * `device_id` - The unique ID of the device that owns this machine.
|
||||
///
|
||||
/// * `path` - The path where the state of the machine should be persisted.
|
||||
pub fn new(user_id: &str, device_id: &str, path: &str) -> Result<Self, MachineCreationError> {
|
||||
pub fn new(user_id: &str, device_id: &str, path: &str) -> Result<Self, CryptoStoreError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
let device_id = device_id.into();
|
||||
let runtime = Runtime::new().unwrap();
|
||||
|
@ -91,6 +93,67 @@ impl OlmMachine {
|
|||
self.inner.device_id().to_string()
|
||||
}
|
||||
|
||||
/// Get the display name of our own device.
|
||||
pub fn display_name(&self) -> Result<Option<String>, CryptoStoreError> {
|
||||
Ok(self.runtime.block_on(self.inner.dislpay_name())?)
|
||||
}
|
||||
|
||||
/// Get a cross signing user identity for the given user ID.
|
||||
pub fn get_identity(&self, user_id: &str) -> Result<Option<UserIdentity>, CryptoStoreError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
|
||||
Ok(
|
||||
if let Some(identity) = self.runtime.block_on(self.inner.get_identity(&user_id))? {
|
||||
Some(self.runtime.block_on(UserIdentity::from_rust(identity))?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if a user identity is considered to be verified by us.
|
||||
pub fn is_identity_verified(&self, user_id: &str) -> Result<bool, CryptoStoreError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
|
||||
Ok(
|
||||
if let Some(identity) = self.runtime.block_on(self.inner.get_identity(&user_id))? {
|
||||
match identity {
|
||||
UserIdentities::Own(i) => i.is_verified(),
|
||||
UserIdentities::Other(i) => i.verified(),
|
||||
}
|
||||
} else {
|
||||
false
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Manually the user with the given user ID.
|
||||
///
|
||||
/// This method will attempt to sign the user identity using either our
|
||||
/// private cross signing key, for other user identities, or our device keys
|
||||
/// for our own user identity.
|
||||
///
|
||||
/// This methid can fail if we don't have the private part of our user-signing
|
||||
/// key.
|
||||
///
|
||||
/// Returns a request that needs to be sent out for the user identity to be
|
||||
/// marked as verified.
|
||||
pub fn verify_identity(&self, user_id: &str) -> Result<SignatureUploadRequest, SignatureError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
|
||||
let user_identity = self.runtime.block_on(self.inner.get_identity(&user_id))?;
|
||||
|
||||
if let Some(user_identity) = user_identity {
|
||||
Ok(match user_identity {
|
||||
UserIdentities::Own(i) => self.runtime.block_on(i.verify())?,
|
||||
UserIdentities::Other(i) => self.runtime.block_on(i.verify())?,
|
||||
}
|
||||
.into())
|
||||
} else {
|
||||
Err(SignatureError::UnknownUserIdentity(user_id.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a `Device` from the store.
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -111,6 +174,39 @@ impl OlmMachine {
|
|||
.map(|d| d.into()))
|
||||
}
|
||||
|
||||
/// Manually the device of the given user with the given device ID.
|
||||
///
|
||||
/// This method will attempt to sign the device using our private cross
|
||||
/// signing key.
|
||||
///
|
||||
/// This method will always fail if the device belongs to someone else, we
|
||||
/// can only sign our own devices.
|
||||
///
|
||||
/// It can also fail if we don't have the private part of our self-signing
|
||||
/// key.
|
||||
///
|
||||
/// Returns a request that needs to be sent out for the device to be marked
|
||||
/// as verified.
|
||||
pub fn verify_device(
|
||||
&self,
|
||||
user_id: &str,
|
||||
device_id: &str,
|
||||
) -> Result<SignatureUploadRequest, SignatureError> {
|
||||
let user_id = UserId::try_from(user_id)?;
|
||||
let device = self
|
||||
.runtime
|
||||
.block_on(self.inner.get_device(&user_id, device_id.into()))?;
|
||||
|
||||
if let Some(device) = device {
|
||||
Ok(self.runtime.block_on(device.verify())?.into())
|
||||
} else {
|
||||
Err(SignatureError::UnknownDevice(
|
||||
user_id.to_string(),
|
||||
device_id.to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark the device of the given user with the given device id as trusted.
|
||||
pub fn mark_device_as_trusted(
|
||||
&self,
|
||||
|
@ -206,6 +302,9 @@ impl OlmMachine {
|
|||
RequestType::KeysClaim => {
|
||||
KeysClaimResponse::try_from_http_response(response).map(Into::into)
|
||||
}
|
||||
RequestType::SignatureUpload => {
|
||||
SignatureUploadResponse::try_from_http_response(response).map(Into::into)
|
||||
}
|
||||
}
|
||||
.expect("Can't convert json string to response");
|
||||
|
||||
|
@ -305,21 +404,7 @@ impl OlmMachine {
|
|||
Ok(self
|
||||
.runtime
|
||||
.block_on(self.inner.get_missing_sessions(users.iter()))?
|
||||
.map(|(request_id, request)| Request::KeysClaim {
|
||||
request_id: request_id.to_string(),
|
||||
one_time_keys: request
|
||||
.one_time_keys
|
||||
.into_iter()
|
||||
.map(|(u, d)| {
|
||||
(
|
||||
u.to_string(),
|
||||
d.into_iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}))
|
||||
.map(|r| r.into()))
|
||||
}
|
||||
|
||||
/// Share a room key with the given list of users for the given room.
|
||||
|
@ -867,6 +952,8 @@ impl OlmMachine {
|
|||
if let Some(verification) = self.inner.get_verification(&user_id, flow_id) {
|
||||
match verification {
|
||||
RustVerification::SasV1(v) => {
|
||||
// TODO there's a signature upload request here, we'll
|
||||
// want to return that one as well.
|
||||
self.runtime.block_on(v.confirm())?.0.map(|r| r.into())
|
||||
}
|
||||
RustVerification::QrV1(v) => v.confirm_scanning().map(|r| r.into()),
|
||||
|
@ -1114,4 +1201,49 @@ impl OlmMachine {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new private cross signing identity and create a request to
|
||||
/// upload the public part of it to the server.
|
||||
pub fn bootstrap_cross_signing(&self) -> Result<BootstrapCrossSigningResult, CryptoStoreError> {
|
||||
Ok(self
|
||||
.runtime
|
||||
.block_on(self.inner.bootstrap_cross_signing(true))?
|
||||
.into())
|
||||
}
|
||||
|
||||
/// Get the status of the private cross signing keys.
|
||||
///
|
||||
/// This can be used to check which private cross signing keys we have
|
||||
/// stored locally.
|
||||
pub fn cross_signing_status(&self) -> CrossSigningStatus {
|
||||
self.runtime
|
||||
.block_on(self.inner.cross_signing_status())
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Export all our private cross signing keys.
|
||||
///
|
||||
/// The export will contain the seed for the ed25519 keys as a base64
|
||||
/// encoded string.
|
||||
///
|
||||
/// This method returns `None` if we don't have any private cross signing keys.
|
||||
pub fn export_cross_signing_keys(&self) -> Option<CrossSigningKeyExport> {
|
||||
self.runtime
|
||||
.block_on(self.inner.export_cross_signing_keys())
|
||||
.map(|e| e.into())
|
||||
}
|
||||
|
||||
/// Import our private cross signing keys.
|
||||
///
|
||||
/// The export needs to contain the seed for the ed25519 keys as a base64
|
||||
/// encoded string.
|
||||
pub fn import_cross_signing_keys(
|
||||
&self,
|
||||
export: CrossSigningKeyExport,
|
||||
) -> Result<(), SecretImportError> {
|
||||
self.runtime
|
||||
.block_on(self.inner.import_cross_signing_keys(export.into()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,18 +10,28 @@ callback interface ProgressListener {
|
|||
void on_progress(i32 progress, i32 total);
|
||||
};
|
||||
|
||||
[Error]
|
||||
enum MachineCreationError {
|
||||
"Identifier",
|
||||
"CryptoStore",
|
||||
};
|
||||
|
||||
[Error]
|
||||
enum KeyImportError {
|
||||
"Export",
|
||||
"CryptoStore",
|
||||
};
|
||||
|
||||
[Error]
|
||||
enum SignatureError {
|
||||
"Signature",
|
||||
"Identifier",
|
||||
"CryptoStore",
|
||||
"UnknownDevice",
|
||||
"UnknownUserIdentity",
|
||||
};
|
||||
|
||||
[Error]
|
||||
enum SecretImportError {
|
||||
"Import",
|
||||
"CryptoStore",
|
||||
};
|
||||
|
||||
|
||||
[Error]
|
||||
enum CryptoStoreError {
|
||||
"CryptoStore",
|
||||
|
@ -65,6 +75,45 @@ dictionary Device {
|
|||
boolean cross_signing_trusted;
|
||||
};
|
||||
|
||||
[Enum]
|
||||
interface UserIdentity {
|
||||
Own(
|
||||
string user_id,
|
||||
boolean trusts_our_own_device,
|
||||
string master_key,
|
||||
string self_signing_key,
|
||||
string user_signing_key
|
||||
);
|
||||
Other(
|
||||
string user_id,
|
||||
string master_key,
|
||||
string self_signing_key
|
||||
);
|
||||
};
|
||||
|
||||
dictionary CrossSigningStatus {
|
||||
boolean has_master;
|
||||
boolean has_self_signing;
|
||||
boolean has_user_signing;
|
||||
};
|
||||
|
||||
dictionary CrossSigningKeyExport {
|
||||
string? master_key;
|
||||
string? self_signing_key;
|
||||
string? user_signing_key;
|
||||
};
|
||||
|
||||
dictionary UploadSigningKeysRequest {
|
||||
string master_key;
|
||||
string self_signing_key;
|
||||
string user_signing_key;
|
||||
};
|
||||
|
||||
dictionary BootstrapCrossSigningResult {
|
||||
UploadSigningKeysRequest upload_signing_keys_request;
|
||||
SignatureUploadRequest signature_request;
|
||||
};
|
||||
|
||||
dictionary CancelInfo {
|
||||
string cancel_code;
|
||||
string reason;
|
||||
|
@ -155,6 +204,11 @@ interface Request {
|
|||
KeysQuery(string request_id, sequence<string> users);
|
||||
KeysClaim(string request_id, record<DOMString, record<DOMString, string>> one_time_keys);
|
||||
RoomMessage(string request_id, string room_id, string event_type, string content);
|
||||
SignatureUpload(string request_id, string body);
|
||||
};
|
||||
|
||||
dictionary SignatureUploadRequest {
|
||||
string body;
|
||||
};
|
||||
|
||||
enum RequestType {
|
||||
|
@ -162,10 +216,11 @@ enum RequestType {
|
|||
"KeysClaim",
|
||||
"KeysUpload",
|
||||
"ToDevice",
|
||||
"SignatureUpload",
|
||||
};
|
||||
|
||||
interface OlmMachine {
|
||||
[Throws=MachineCreationError]
|
||||
[Throws=CryptoStoreError]
|
||||
constructor([ByRef] string user_id, [ByRef] string device_id, [ByRef] string path);
|
||||
|
||||
record<DOMString, string> identity_keys();
|
||||
|
@ -190,10 +245,16 @@ interface OlmMachine {
|
|||
[Throws=CryptoStoreError]
|
||||
string encrypt([ByRef] string room_id, [ByRef] string event_type, [ByRef] string content);
|
||||
|
||||
[Throws=CryptoStoreError]
|
||||
UserIdentity? get_identity([ByRef] string user_id);
|
||||
[Throws=SignatureError]
|
||||
SignatureUploadRequest verify_identity([ByRef] string user_id);
|
||||
[Throws=CryptoStoreError]
|
||||
Device? get_device([ByRef] string user_id, [ByRef] string device_id);
|
||||
[Throws=CryptoStoreError]
|
||||
void mark_device_as_trusted([ByRef] string user_id, [ByRef] string device_id);
|
||||
[Throws=SignatureError]
|
||||
SignatureUploadRequest verify_device([ByRef] string user_id, [ByRef] string device_id);
|
||||
[Throws=CryptoStoreError]
|
||||
sequence<Device> get_user_devices([ByRef] string user_id);
|
||||
|
||||
|
@ -268,4 +329,13 @@ interface OlmMachine {
|
|||
);
|
||||
[Throws=CryptoStoreError]
|
||||
void discard_room_key([ByRef] string room_id);
|
||||
|
||||
CrossSigningStatus cross_signing_status();
|
||||
[Throws=CryptoStoreError]
|
||||
BootstrapCrossSigningResult bootstrap_cross_signing();
|
||||
CrossSigningKeyExport? export_cross_signing_keys();
|
||||
[Throws=SecretImportError]
|
||||
void import_cross_signing_keys(CrossSigningKeyExport export);
|
||||
[Throws=CryptoStoreError]
|
||||
boolean is_identity_verified([ByRef] string user_id);
|
||||
};
|
||||
|
|
|
@ -3,13 +3,18 @@
|
|||
use std::{collections::HashMap, convert::TryFrom};
|
||||
|
||||
use http::Response;
|
||||
use matrix_sdk_common::uuid::Uuid;
|
||||
use serde_json::json;
|
||||
|
||||
use ruma::{
|
||||
api::client::r0::{
|
||||
keys::{
|
||||
claim_keys::Response as KeysClaimResponse, get_keys::Response as KeysQueryResponse,
|
||||
claim_keys::{Request as KeysClaimRequest, Response as KeysClaimResponse},
|
||||
get_keys::Response as KeysQueryResponse,
|
||||
upload_keys::Response as KeysUploadResponse,
|
||||
upload_signatures::{
|
||||
Request as RustSignatureUploadRequest, Response as SignatureUploadResponse,
|
||||
},
|
||||
},
|
||||
sync::sync_events::DeviceLists as RumaDeviceLists,
|
||||
to_device::send_event_to_device::Response as ToDeviceResponse,
|
||||
|
@ -21,9 +26,65 @@ use ruma::{
|
|||
|
||||
use matrix_sdk_crypto::{
|
||||
IncomingResponse, OutgoingRequest, OutgoingVerificationRequest as SdkVerificationRequest,
|
||||
RoomMessageRequest, ToDeviceRequest,
|
||||
RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest as RustUploadSigningKeysRequest,
|
||||
};
|
||||
|
||||
pub struct SignatureUploadRequest {
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
impl From<RustSignatureUploadRequest> for SignatureUploadRequest {
|
||||
fn from(r: RustSignatureUploadRequest) -> Self {
|
||||
Self {
|
||||
body: serde_json::to_string(&r.signed_keys)
|
||||
.expect("Can't serialize signature upload request"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UploadSigningKeysRequest {
|
||||
pub master_key: String,
|
||||
pub self_signing_key: String,
|
||||
pub user_signing_key: String,
|
||||
}
|
||||
|
||||
impl From<RustUploadSigningKeysRequest> for UploadSigningKeysRequest {
|
||||
fn from(r: RustUploadSigningKeysRequest) -> Self {
|
||||
Self {
|
||||
master_key: serde_json::to_string(
|
||||
&r.master_key.expect("Request didn't contain a master key"),
|
||||
)
|
||||
.expect("Can't serialize cross signing master key"),
|
||||
self_signing_key: serde_json::to_string(
|
||||
&r.self_signing_key
|
||||
.expect("Request didn't contain a self-signing key"),
|
||||
)
|
||||
.expect("Can't serialize cross signing self-signing key"),
|
||||
user_signing_key: serde_json::to_string(
|
||||
&r.user_signing_key
|
||||
.expect("Request didn't contain a user-signing key"),
|
||||
)
|
||||
.expect("Can't serialize cross signing user-signing key"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BootstrapCrossSigningResult {
|
||||
pub upload_signing_keys_request: UploadSigningKeysRequest,
|
||||
pub signature_request: SignatureUploadRequest,
|
||||
}
|
||||
|
||||
impl From<(RustUploadSigningKeysRequest, RustSignatureUploadRequest)>
|
||||
for BootstrapCrossSigningResult
|
||||
{
|
||||
fn from(requests: (RustUploadSigningKeysRequest, RustSignatureUploadRequest)) -> Self {
|
||||
Self {
|
||||
upload_signing_keys_request: requests.0.into(),
|
||||
signature_request: requests.1.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum OutgoingVerificationRequest {
|
||||
ToDevice {
|
||||
request_id: String,
|
||||
|
@ -87,6 +148,10 @@ pub enum Request {
|
|||
event_type: String,
|
||||
content: String,
|
||||
},
|
||||
SignatureUpload {
|
||||
request_id: String,
|
||||
body: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<OutgoingRequest> for Request {
|
||||
|
@ -114,8 +179,13 @@ impl From<OutgoingRequest> for Request {
|
|||
}
|
||||
}
|
||||
ToDeviceRequest(t) => Request::from(t),
|
||||
SignatureUpload(_) => todo!("Uploading signatures isn't yet supported"),
|
||||
SignatureUpload(t) => Request::SignatureUpload {
|
||||
request_id: r.request_id().to_string(),
|
||||
body: serde_json::to_string(&t.signed_keys)
|
||||
.expect("Can't serialize signature upload request"),
|
||||
},
|
||||
RoomMessage(r) => Request::from(r),
|
||||
KeysClaim(c) => (*r.request_id(), c.clone()).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,6 +200,28 @@ impl From<ToDeviceRequest> for Request {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<(Uuid, KeysClaimRequest)> for Request {
|
||||
fn from(request_tuple: (Uuid, KeysClaimRequest)) -> Self {
|
||||
let (request_id, request) = request_tuple;
|
||||
|
||||
Request::KeysClaim {
|
||||
request_id: request_id.to_string(),
|
||||
one_time_keys: request
|
||||
.one_time_keys
|
||||
.into_iter()
|
||||
.map(|(u, d)| {
|
||||
(
|
||||
u.to_string(),
|
||||
d.into_iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ToDeviceRequest> for Request {
|
||||
fn from(r: &ToDeviceRequest) -> Self {
|
||||
Request::ToDevice {
|
||||
|
@ -163,6 +255,7 @@ pub enum RequestType {
|
|||
KeysClaim,
|
||||
KeysUpload,
|
||||
ToDevice,
|
||||
SignatureUpload,
|
||||
}
|
||||
|
||||
pub struct DeviceLists {
|
||||
|
@ -197,6 +290,7 @@ pub(crate) enum OwnedResponse {
|
|||
KeysUpload(KeysUploadResponse),
|
||||
KeysQuery(KeysQueryResponse),
|
||||
ToDevice(ToDeviceResponse),
|
||||
SignatureUpload(SignatureUploadResponse),
|
||||
}
|
||||
|
||||
impl From<KeysClaimResponse> for OwnedResponse {
|
||||
|
@ -223,6 +317,12 @@ impl From<ToDeviceResponse> for OwnedResponse {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<SignatureUploadResponse> for OwnedResponse {
|
||||
fn from(response: SignatureUploadResponse) -> Self {
|
||||
Self::SignatureUpload(response)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<IncomingResponse<'a>> for &'a OwnedResponse {
|
||||
fn into(self) -> IncomingResponse<'a> {
|
||||
match self {
|
||||
|
@ -230,6 +330,7 @@ impl<'a> Into<IncomingResponse<'a>> for &'a OwnedResponse {
|
|||
OwnedResponse::KeysQuery(r) => IncomingResponse::KeysQuery(r),
|
||||
OwnedResponse::KeysUpload(r) => IncomingResponse::KeysUpload(r),
|
||||
OwnedResponse::ToDevice(r) => IncomingResponse::ToDevice(r),
|
||||
OwnedResponse::SignatureUpload(r) => IncomingResponse::SignatureUpload(r),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
61
rust-sdk/src/users.rs
Normal file
61
rust-sdk/src/users.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use matrix_sdk_crypto::UserIdentities;
|
||||
use ruma::encryption::CrossSigningKey;
|
||||
|
||||
use crate::CryptoStoreError;
|
||||
|
||||
/// Enum representing cross signing identities of our own user or some other
|
||||
/// user.
|
||||
pub enum UserIdentity {
|
||||
/// Our own user identity.
|
||||
Own {
|
||||
/// The unique id of our own user.
|
||||
user_id: String,
|
||||
/// Does our own user identity trust our own device.
|
||||
trusts_our_own_device: bool,
|
||||
/// The public master key of our identity.
|
||||
master_key: String,
|
||||
/// The public user-signing key of our identity.
|
||||
user_signing_key: String,
|
||||
/// The public self-signing key of our identity.
|
||||
self_signing_key: String,
|
||||
},
|
||||
/// The user identity of other users.
|
||||
Other {
|
||||
/// The unique id of the user.
|
||||
user_id: String,
|
||||
/// The public master key of the identity.
|
||||
master_key: String,
|
||||
/// The public self-signing key of our identity.
|
||||
self_signing_key: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl UserIdentity {
|
||||
pub(crate) async fn from_rust(i: UserIdentities) -> Result<Self, CryptoStoreError> {
|
||||
Ok(match i {
|
||||
UserIdentities::Own(i) => {
|
||||
let master: CrossSigningKey = i.master_key().to_owned().into();
|
||||
let user_signing: CrossSigningKey = i.user_signing_key().to_owned().into();
|
||||
let self_signing: CrossSigningKey = i.self_signing_key().to_owned().into();
|
||||
|
||||
UserIdentity::Own {
|
||||
user_id: i.user_id().to_string(),
|
||||
trusts_our_own_device: i.trusts_our_own_device().await?,
|
||||
master_key: serde_json::to_string(&master)?,
|
||||
user_signing_key: serde_json::to_string(&user_signing)?,
|
||||
self_signing_key: serde_json::to_string(&self_signing)?,
|
||||
}
|
||||
}
|
||||
UserIdentities::Other(i) => {
|
||||
let master: CrossSigningKey = i.master_key().to_owned().into();
|
||||
let self_signing: CrossSigningKey = i.self_signing_key().to_owned().into();
|
||||
|
||||
UserIdentity::Other {
|
||||
user_id: i.user_id().to_string(),
|
||||
master_key: serde_json::to_string(&master)?,
|
||||
self_signing_key: serde_json::to_string(&self_signing)?,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue