From 5d4b3a0457ef3c8bdfe9b031e474c78be7adff7e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 31 May 2022 17:15:37 +0200 Subject: [PATCH] feat(crypto-nodejs): Implement `OlmMachine.decrypt_room_event`. --- crates/matrix-sdk-crypto-nodejs/Cargo.toml | 1 + .../matrix-sdk-crypto-nodejs/src/machine.rs | 19 +++- .../matrix-sdk-crypto-nodejs/src/responses.rs | 94 ++++++++++++++++++- 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/crates/matrix-sdk-crypto-nodejs/Cargo.toml b/crates/matrix-sdk-crypto-nodejs/Cargo.toml index c00cfafd1..6c6d04adf 100644 --- a/crates/matrix-sdk-crypto-nodejs/Cargo.toml +++ b/crates/matrix-sdk-crypto-nodejs/Cargo.toml @@ -25,6 +25,7 @@ docsrs = [] [dependencies] matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto" } +matrix-sdk-common = { version = "0.5.0", path = "../matrix-sdk-common" } ruma = { version = "0.6.2", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "d0e744287a14319c2a9148fef3747548c740fc36" } napi = { git = "https://github.com/Hywan/napi-rs", branch = "feat-tonapivalue-u16", default-features = false, features = ["napi4", "tokio_rt"] } diff --git a/crates/matrix-sdk-crypto-nodejs/src/machine.rs b/crates/matrix-sdk-crypto-nodejs/src/machine.rs index 4e9ef5eeb..fbf4ab3ee 100644 --- a/crates/matrix-sdk-crypto-nodejs/src/machine.rs +++ b/crates/matrix-sdk-crypto-nodejs/src/machine.rs @@ -7,7 +7,10 @@ use std::{ use napi::bindgen_prelude::{Either3, Either5, ToNapiValue}; use napi_derive::*; -use ruma::{DeviceKeyAlgorithm, OwnedTransactionId, UInt}; +use ruma::{ + events::room::encrypted::OriginalSyncRoomEncryptedEvent, DeviceKeyAlgorithm, + OwnedTransactionId, UInt, +}; use serde_json::Value as JsonValue; use crate::{ @@ -228,6 +231,20 @@ impl OlmMachine { ) .map_err(into_err) } + + #[napi] + pub async fn decrypt_room_event( + &self, + event: String, + room_id: &identifiers::RoomId, + ) -> Result { + let event: OriginalSyncRoomEncryptedEvent = + serde_json::from_str(event.as_str()).map_err(into_err)?; + let room_id = room_id.inner.clone(); + let room_event = self.inner.decrypt_room_event(&event, &room_id).await.map_err(into_err)?; + + Ok(room_event.into()) + } } /// An Ed25519 public key, used to verify digital signatures. diff --git a/crates/matrix-sdk-crypto-nodejs/src/responses.rs b/crates/matrix-sdk-crypto-nodejs/src/responses.rs index 1594c7142..fc52be62e 100644 --- a/crates/matrix-sdk-crypto-nodejs/src/responses.rs +++ b/crates/matrix-sdk-crypto-nodejs/src/responses.rs @@ -1,4 +1,7 @@ +use matrix_sdk_common::deserialized_responses::{AlgorithmInfo, EncryptionInfo}; use matrix_sdk_crypto::IncomingResponse; +use napi::bindgen_prelude::ToNapiValue; +use napi_derive::*; pub(crate) use ruma::api::client::{ backup::add_backup_keys::v3::Response as KeysBackupResponse, keys::{ @@ -11,7 +14,7 @@ pub(crate) use ruma::api::client::{ }; use ruma::api::IncomingResponse as RumaIncomingResponse; -use crate::{into_err, requests::RequestType}; +use crate::{identifiers, into_err, requests::RequestType}; pub(crate) fn response_from_string(body: &str) -> http::Result>> { http::Response::builder().status(200).body(body.as_bytes().to_vec()) @@ -123,3 +126,92 @@ impl<'a> From<&'a OwnedResponse> for IncomingResponse<'a> { } } } + +#[napi] +pub struct DecryptedRoomEvent { + pub event: String, + encryption_info: Option, +} + +#[napi] +impl DecryptedRoomEvent { + /// The user ID of the event sender, note this is untrusted data + /// unless the `verification_state` is as well trusted. + #[napi(getter)] + pub fn sender(&self) -> Option { + Some(identifiers::UserId::new_with(self.encryption_info.as_ref()?.sender.clone())) + } + + /// The device ID of the device that sent us the event, note this + /// is untrusted data unless `verification_state` is as well + /// trusted. + #[napi(getter)] + pub fn sender_device(&self) -> Option { + Some(identifiers::DeviceId::new_with(self.encryption_info.as_ref()?.sender_device.clone())) + } + + /// The Curve25519 key of the device that created the megolm + /// decryption key originally. + #[napi(getter)] + pub fn sender_curve25519_key(&self) -> Option { + Some(match &self.encryption_info.as_ref()?.algorithm_info { + AlgorithmInfo::MegolmV1AesSha2 { curve25519_key, .. } => curve25519_key.clone(), + }) + } + + /// The signing Ed25519 key that have created the megolm key that + /// was used to decrypt this session. + #[napi(getter)] + pub fn sender_claimed_ed25519_key(&self) -> Option { + match &self.encryption_info.as_ref()?.algorithm_info { + AlgorithmInfo::MegolmV1AesSha2 { sender_claimed_keys, .. } => { + sender_claimed_keys.get(&ruma::DeviceKeyAlgorithm::Ed25519).cloned() + } + } + } + + /// Chain of Curve25519 keys through which this session was + /// forwarded, via `m.forwarded_room_key` events. + #[napi(getter)] + pub fn forwarding_curve25519_key_chain(&self) -> Option> { + Some(match &self.encryption_info.as_ref()?.algorithm_info { + AlgorithmInfo::MegolmV1AesSha2 { forwarding_curve25519_key_chain, .. } => { + forwarding_curve25519_key_chain.clone() + } + }) + } + + /// The verification state of the device that sent us the event, + /// note this is the state of the device at the time of + /// decryption. It may change in the future if a device gets + /// verified or deleted. + #[napi(getter)] + pub fn verification_state(&self) -> Option { + Some((&self.encryption_info.as_ref()?.verification_state).into()) + } +} + +impl From for DecryptedRoomEvent { + fn from(value: matrix_sdk_common::deserialized_responses::RoomEvent) -> Self { + Self { event: value.event.json().get().to_owned(), encryption_info: value.encryption_info } + } +} + +#[napi] +pub enum VerificationState { + Trusted, + Untrusted, + UnknownDevice, +} + +impl From<&matrix_sdk_common::deserialized_responses::VerificationState> for VerificationState { + fn from(value: &matrix_sdk_common::deserialized_responses::VerificationState) -> Self { + use matrix_sdk_common::deserialized_responses::VerificationState::*; + + match value { + Trusted => Self::Trusted, + Untrusted => Self::Untrusted, + UnknownDevice => Self::UnknownDevice, + } + } +}