diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..ece8c47c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,103 @@ +name: CI + +on: + push: + pull_request: + branches: [ master ] + +env: + CARGO_TERM_COLOR: always + +jobs: + style: + name: Check style + runs-on: ubuntu-latest + + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: rustfmt + profile: minimal + override: true + + - name: Cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + clippy: + name: Run clippy + needs: [style] + runs-on: ubuntu-latest + + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: clippy + profile: minimal + override: true + + - name: Clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all-targets -- -D warnings + + test: + name: ${{ matrix.name }} + needs: [clippy] + + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + strategy: + matrix: + name: + - linux / stable + - linux / beta + - macOS / stable + - windows / stable-x86_64-msvc + + include: + - name: linux / stable + + - name: linux / beta + rust: beta + + - name: macOS / stable + os: macOS-latest + + - name: windows / stable-x86_64-msvc + os: windows-latest + target: x86_64-pc-windows-msvc + + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust || 'stable' }} + target: ${{ matrix.target }} + profile: minimal + override: true + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + + - name: Test + uses: actions-rs/cargo@v1 + with: + command: test diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..8b9076e1 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,39 @@ +name: Code coverage + +on: + push: + branches: [ master ] + +env: + CARGO_TERM_COLOR: always + +jobs: + code_coverage: + name: Code Coverage + runs-on: "ubuntu-latest" + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + + - name: Install tarpaulin + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-tarpaulin -f + + - name: Run tarpaulin + uses: actions-rs/cargo@v1 + with: + command: tarpaulin + args: --ignore-config --exclude-files "matrix_sdk/examples/*,matrix_sdk_common,matrix_sdk_test" --out Xml + + - name: Upload to codecov.io + uses: codecov/codecov-action@v1 diff --git a/README.md b/README.md index 2768c56f..7b5dc261 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://img.shields.io/travis/matrix-org/matrix-rust-sdk.svg?style=flat-square)](https://travis-ci.org/matrix-org/matrix-rust-sdk) +![Build Status](https://img.shields.io/github/workflow/status/matrix-org/matrix-rust-sdk/CI?style=flat-square) [![codecov](https://img.shields.io/codecov/c/github/matrix-org/matrix-rust-sdk/master.svg?style=flat-square)](https://codecov.io/gh/matrix-org/matrix-rust-sdk) [![License](https://img.shields.io/badge/License-Apache%202.0-yellowgreen.svg?style=flat-square)](https://opensource.org/licenses/Apache-2.0) [![#matrix-rust-sdk](https://img.shields.io/badge/matrix-%23matrix--rust--sdk-blue?style=flat-square)](https://matrix.to/#/#matrix-rust-sdk:matrix.org) diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index 652b8410..0690bea3 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -76,6 +76,7 @@ use matrix_sdk_common::{ join_room_by_id, join_room_by_id_or_alias, kick_user, leave_room, Invite3pid, }, message::{get_message_events, send_message_event}, + profile::{get_avatar_url, get_display_name, set_avatar_url, set_display_name}, read_marker::set_read_marker, receipt::create_receipt, room::create_room, @@ -430,11 +431,121 @@ impl Client { session.as_ref().cloned().map(|s| s.user_id) } + /// Fetches the display name of the owner of the client. + /// + /// # Example + /// ```no_run + /// # use futures::executor::block_on; + /// # use matrix_sdk::Client; + /// # use url::Url; + /// # let homeserver = Url::parse("http://example.com").unwrap(); + /// # block_on(async { + /// let user = "example"; + /// let client = Client::new(homeserver).unwrap(); + /// client.login(user, "password", None, None).await.unwrap(); + /// + /// if let Some(name) = client.display_name().await.unwrap() { + /// println!("Logged in as user '{}' with display name '{}'", user, name); + /// } + /// # }) + /// ``` + pub async fn display_name(&self) -> Result> { + let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?; + let request = get_display_name::Request::new(&user_id); + let response = self.send(request).await?; + Ok(response.displayname) + } + + /// Sets the display name of the owner of the client. + /// + /// # Example + /// ```no_run + /// # use futures::executor::block_on; + /// # use matrix_sdk::Client; + /// # use url::Url; + /// # let homeserver = Url::parse("http://example.com").unwrap(); + /// # block_on(async { + /// let user = "example"; + /// let client = Client::new(homeserver).unwrap(); + /// client.login(user, "password", None, None).await.unwrap(); + /// + /// client.set_display_name(Some("Alice")).await.expect("Failed setting display name"); + /// # }) + /// ``` + pub async fn set_display_name(&self, name: Option<&str>) -> Result<()> { + let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?; + let request = set_display_name::Request::new(&user_id, name); + self.send(request).await?; + Ok(()) + } + + /// Gets the mxc avatar url of the owner of the client, if set. + /// + /// # Example + /// ```no_run + /// # use futures::executor::block_on; + /// # use matrix_sdk::Client; + /// # use url::Url; + /// # let homeserver = Url::parse("http://example.com").unwrap(); + /// # block_on(async { + /// # let user = "example"; + /// let client = Client::new(homeserver).unwrap(); + /// client.login(user, "password", None, None).await.unwrap(); + /// + /// if let Some(url) = client.avatar_url().await.unwrap() { + /// println!("Your avatar's mxc url is {}", url); + /// } + /// # }) + /// ``` + pub async fn avatar_url(&self) -> Result> { + let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?; + let request = get_avatar_url::Request::new(&user_id); + let response = self.send(request).await?; + Ok(response.avatar_url) + } + + /// Sets the mxc avatar url of the client's owner. The avatar gets unset if `url` is `None`. + pub async fn set_avatar_url(&self, url: Option<&str>) -> Result<()> { + let user_id = self.user_id().await.ok_or(Error::AuthenticationRequired)?; + let request = set_avatar_url::Request::new(&user_id, url); + self.send(request).await?; + Ok(()) + } + + /// Upload and set the owning client's avatar. + /// + /// The will upload the data produced by the reader to the homeserver's content repository, and + /// set the user's avatar to the mxc url for the uploaded file. + /// + /// This is a convenience method for calling [`upload()`](#method.upload), followed by + /// [`set_avatar_url()`](#method.set_avatar_url). + /// + /// # Example + /// ```no_run + /// # use std::{path::Path, fs::File, io::Read}; + /// # use futures::executor::block_on; + /// # use matrix_sdk::Client; + /// # use url::Url; + /// # block_on(async { + /// # let homeserver = Url::parse("http://locahost:8080").unwrap(); + /// # let client = Client::new(homeserver).unwrap(); + /// let path = Path::new("/home/example/selfie.jpg"); + /// let mut image = File::open(&path).unwrap(); + /// + /// client.upload_avatar(&mime::IMAGE_JPEG, &mut image).await.expect("Can't set avatar"); + /// # }) + /// ``` + pub async fn upload_avatar(&self, content_type: &Mime, reader: &mut R) -> Result<()> { + let upload_response = self.upload(content_type, reader).await?; + self.set_avatar_url(Some(&upload_response.content_uri)) + .await?; + Ok(()) + } + ///// Add `EventEmitter` to `Client`. ///// ///// The methods of `EventEmitter` are called when the respective `RoomEvents` occur. //pub async fn add_event_emitter(&mut self, emitter: Box) { - // self.base_client.add_event_emitter(emitter).await; //} // /// Returns the joined rooms this client knows about. @@ -803,7 +914,7 @@ impl Client { since: Option<&str>, server: Option<&ServerName>, ) -> Result { - let limit = limit.map(|n| UInt::from(n)); + let limit = limit.map(UInt::from); let request = assign!(get_public_rooms::Request::new(), { limit, diff --git a/matrix_sdk_common/src/lib.rs b/matrix_sdk_common/src/lib.rs index 92002cfc..13655d0a 100644 --- a/matrix_sdk_common/src/lib.rs +++ b/matrix_sdk_common/src/lib.rs @@ -8,7 +8,7 @@ pub use ruma::{ AuthScheme, EndpointError, OutgoingRequest, }, directory, encryption, events, identifiers, presence, push, - serde::Raw, + serde::{CanonicalJsonValue, Raw}, thirdparty, Outgoing, }; diff --git a/matrix_sdk_crypto/src/file_encryption/attachments.rs b/matrix_sdk_crypto/src/file_encryption/attachments.rs index 675e9ed7..b578d71c 100644 --- a/matrix_sdk_crypto/src/file_encryption/attachments.rs +++ b/matrix_sdk_crypto/src/file_encryption/attachments.rs @@ -33,7 +33,7 @@ use aes_ctr::{ use base64::DecodeError; use sha2::{Digest, Sha256}; -use super::{decode, decode_url_safe, encode, encode_url_safe}; +use crate::utilities::{decode, decode_url_safe, encode, encode_url_safe}; const IV_SIZE: usize = 16; const KEY_SIZE: usize = 32; diff --git a/matrix_sdk_crypto/src/file_encryption/key_export.rs b/matrix_sdk_crypto/src/file_encryption/key_export.rs index b881ec64..da394edf 100644 --- a/matrix_sdk_crypto/src/file_encryption/key_export.rs +++ b/matrix_sdk_crypto/src/file_encryption/key_export.rs @@ -27,8 +27,10 @@ use hmac::{Hmac, Mac, NewMac}; use pbkdf2::pbkdf2; use sha2::{Sha256, Sha512}; -use super::{decode, encode, DecodeError}; -use crate::olm::ExportedRoomKey; +use crate::{ + olm::ExportedRoomKey, + utilities::{decode, encode, DecodeError}, +}; const SALT_SIZE: usize = 16; const IV_SIZE: usize = 16; diff --git a/matrix_sdk_crypto/src/file_encryption/mod.rs b/matrix_sdk_crypto/src/file_encryption/mod.rs index 45ccd310..41e0b045 100644 --- a/matrix_sdk_crypto/src/file_encryption/mod.rs +++ b/matrix_sdk_crypto/src/file_encryption/mod.rs @@ -3,21 +3,3 @@ mod key_export; pub use attachments::{AttachmentDecryptor, AttachmentEncryptor, DecryptorError}; pub use key_export::{decrypt_key_export, encrypt_key_export}; - -use base64::{decode_config, encode_config, DecodeError, STANDARD_NO_PAD, URL_SAFE_NO_PAD}; - -fn decode(input: impl AsRef<[u8]>) -> Result, DecodeError> { - decode_config(input, STANDARD_NO_PAD) -} - -fn decode_url_safe(input: impl AsRef<[u8]>) -> Result, DecodeError> { - decode_config(input, URL_SAFE_NO_PAD) -} - -pub fn encode(input: impl AsRef<[u8]>) -> String { - encode_config(input, STANDARD_NO_PAD) -} - -pub fn encode_url_safe(input: impl AsRef<[u8]>) -> String { - encode_config(input, URL_SAFE_NO_PAD) -} diff --git a/matrix_sdk_crypto/src/lib.rs b/matrix_sdk_crypto/src/lib.rs index 0a1f0300..f37cf97e 100644 --- a/matrix_sdk_crypto/src/lib.rs +++ b/matrix_sdk_crypto/src/lib.rs @@ -36,6 +36,7 @@ pub mod olm; mod requests; mod session_manager; pub mod store; +mod utilities; mod verification; pub use error::{MegolmError, OlmError}; diff --git a/matrix_sdk_crypto/src/olm/account.rs b/matrix_sdk_crypto/src/olm/account.rs index cf20c691..9b6551bd 100644 --- a/matrix_sdk_crypto/src/olm/account.rs +++ b/matrix_sdk_crypto/src/olm/account.rs @@ -54,10 +54,10 @@ use olm_rs::{ use crate::{ error::{EventError, OlmResult, SessionCreationError}, - file_encryption::encode, identities::ReadOnlyDevice, requests::UploadSigningKeysRequest, store::{Changes, Store}, + utilities::encode, OlmError, }; @@ -170,7 +170,7 @@ impl Account { return Err(OlmError::SessionWedged(user_id, sender_key)); } } - Err(e) => return Err(e.into()), + Err(e) => return Err(e), }; debug!("Decrypted a to-device event {:?}", event); diff --git a/matrix_sdk_crypto/src/olm/group_sessions/mod.rs b/matrix_sdk_crypto/src/olm/group_sessions/mod.rs index 04174fcb..fdd5821e 100644 --- a/matrix_sdk_crypto/src/olm/group_sessions/mod.rs +++ b/matrix_sdk_crypto/src/olm/group_sessions/mod.rs @@ -138,7 +138,7 @@ mod test { use crate::ReadOnlyAccount; #[tokio::test] - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "linux")] async fn expiration() { let settings = EncryptionSettings { rotation_period_msgs: 1, diff --git a/matrix_sdk_crypto/src/olm/signing/pk_signing.rs b/matrix_sdk_crypto/src/olm/signing/pk_signing.rs index fb552349..661c7a61 100644 --- a/matrix_sdk_crypto/src/olm/signing/pk_signing.rs +++ b/matrix_sdk_crypto/src/olm/signing/pk_signing.rs @@ -16,7 +16,6 @@ use aes_gcm::{ aead::{generic_array::GenericArray, Aead, NewAead}, Aes256Gcm, }; -use base64::{decode_config, encode_config, DecodeError, URL_SAFE_NO_PAD}; use getrandom::getrandom; use matrix_sdk_common::{ encryption::DeviceKeys, @@ -42,19 +41,12 @@ use matrix_sdk_common::{ use crate::{ error::SignatureError, identities::{MasterPubkey, SelfSigningPubkey, UserSigningPubkey}, + utilities::{decode_url_safe as decode, encode_url_safe as encode, DecodeError}, UserIdentity, }; const NONCE_SIZE: usize = 12; -fn encode>(input: T) -> String { - encode_config(input, URL_SAFE_NO_PAD) -} - -fn decode>(input: T) -> Result, DecodeError> { - decode_config(input, URL_SAFE_NO_PAD) -} - /// Error type reporting failures in the Signign operations. #[derive(Debug, Error)] pub enum SigningError { diff --git a/matrix_sdk_crypto/src/session_manager/sessions.rs b/matrix_sdk_crypto/src/session_manager/sessions.rs index 2cf2a2cc..95afe118 100644 --- a/matrix_sdk_crypto/src/session_manager/sessions.rs +++ b/matrix_sdk_crypto/src/session_manager/sessions.rs @@ -316,8 +316,7 @@ mod test { use matrix_sdk_common::{ api::r0::keys::claim_keys::Response as KeyClaimResponse, - identifiers::{user_id, DeviceIdBox, DeviceKeyAlgorithm, UserId}, - instant::{Duration, Instant}, + identifiers::{user_id, DeviceIdBox, UserId}, }; use matrix_sdk_test::async_test; @@ -422,8 +421,13 @@ mod test { // This test doesn't run on macos because we're modifying the session // creation time so we can get around the UNWEDGING_INTERVAL. #[async_test] - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "linux")] async fn session_unwedging() { + use matrix_sdk_common::{ + identifiers::DeviceKeyAlgorithm, + instant::{Duration, Instant}, + }; + let manager = session_manager().await; let bob = bob_account(); let (_, mut session) = bob.create_session_for(&manager.account).await; diff --git a/matrix_sdk_crypto/src/utilities.rs b/matrix_sdk_crypto/src/utilities.rs new file mode 100644 index 00000000..fcf6dc5a --- /dev/null +++ b/matrix_sdk_crypto/src/utilities.rs @@ -0,0 +1,36 @@ +// Copyright 2020 The Matrix.org Foundation C.I.C. +// +// 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. + +pub use base64::DecodeError; +use base64::{decode_config, encode_config, STANDARD_NO_PAD, URL_SAFE_NO_PAD}; + +/// Decode the input as base64 with no padding. +pub fn decode(input: impl AsRef<[u8]>) -> Result, DecodeError> { + decode_config(input, STANDARD_NO_PAD) +} + +/// Decode the input as URL safe base64 with no padding. +pub fn decode_url_safe(input: impl AsRef<[u8]>) -> Result, DecodeError> { + decode_config(input, URL_SAFE_NO_PAD) +} + +/// Encode the input as base64 with no padding. +pub fn encode(input: impl AsRef<[u8]>) -> String { + encode_config(input, STANDARD_NO_PAD) +} + +/// Encode the input as URL safe base64 with no padding. +pub fn encode_url_safe(input: impl AsRef<[u8]>) -> String { + encode_config(input, URL_SAFE_NO_PAD) +} diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index c3ba5e88..c81344c3 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -380,7 +380,7 @@ mod test { assert!(bob.is_done()); } - #[cfg(not(target_os = "macos"))] + #[cfg(target_os = "linux")] #[tokio::test] async fn timing_out() { let (alice_machine, bob) = setup_verification_machine().await; diff --git a/matrix_sdk_crypto/src/verification/sas/helpers.rs b/matrix_sdk_crypto/src/verification/sas/helpers.rs index 106727b8..37974d14 100644 --- a/matrix_sdk_crypto/src/verification/sas/helpers.rs +++ b/matrix_sdk_crypto/src/verification/sas/helpers.rs @@ -14,6 +14,7 @@ use std::{collections::BTreeMap, convert::TryInto}; +use sha2::{Digest, Sha256}; use tracing::{trace, warn}; use olm_rs::sas::OlmSas; @@ -21,15 +22,19 @@ use olm_rs::sas::OlmSas; use matrix_sdk_common::{ api::r0::to_device::DeviceIdOrAllDevices, events::{ - key::verification::{cancel::CancelCode, mac::MacToDeviceEventContent}, + key::verification::{ + cancel::CancelCode, mac::MacToDeviceEventContent, start::StartToDeviceEventContent, + }, AnyToDeviceEventContent, EventType, ToDeviceEvent, }, identifiers::{DeviceId, DeviceKeyAlgorithm, DeviceKeyId, UserId}, uuid::Uuid, + CanonicalJsonValue, }; use crate::{ identities::{ReadOnlyDevice, UserIdentities}, + utilities::encode, ReadOnlyAccount, ToDeviceRequest, }; @@ -40,6 +45,29 @@ pub struct SasIds { pub other_identity: Option, } +/// Calculate the commitment for a accept event from the public key and the +/// start event. +/// +/// # Arguments +/// +/// * `public_key` - Our own ephemeral public key that is used for the +/// interactive verification. +/// +/// * `content` - The `m.key.verification.start` event content that started the +/// interactive verification process. +pub fn calculate_commitment(public_key: &str, content: &StartToDeviceEventContent) -> String { + let json_content: CanonicalJsonValue = serde_json::to_value(content) + .expect("Can't serialize content") + .try_into() + .expect("Can't canonicalize content"); + + encode( + Sha256::new() + .chain(&format!("{}{}", public_key, json_content)) + .finalize(), + ) +} + /// Get a tuple of an emoji and a description of the emoji using a number. /// /// This is taken directly from the [spec] @@ -493,12 +521,38 @@ pub fn content_to_request( #[cfg(test)] mod test { + use matrix_sdk_common::events::key::verification::start::StartToDeviceEventContent; use proptest::prelude::*; + use serde_json::json; - use super::{bytes_to_decimal, bytes_to_emoji, bytes_to_emoji_index, emoji_from_index}; + use super::{ + bytes_to_decimal, bytes_to_emoji, bytes_to_emoji_index, calculate_commitment, + emoji_from_index, + }; #[test] - fn test_emoji_generation() { + fn commitment_calculation() { + let commitment = "CCQmB4JCdB0FW21FdAnHj/Hu8+W9+Nb0vgwPEnZZQ4g"; + + let public_key = "Q/NmNFEUS1fS+YeEmiZkjjblKTitrKOAk7cPEumcMlg"; + let content = json!({ + "from_device":"XOWLHHFSWM", + "transaction_id":"bYxBsirjUJO9osar6ST4i2M2NjrYLA7l", + "method":"m.sas.v1", + "key_agreement_protocols":["curve25519-hkdf-sha256","curve25519"], + "hashes":["sha256"], + "message_authentication_codes":["hkdf-hmac-sha256","hmac-sha256"], + "short_authentication_string":["decimal","emoji"] + }); + + let content: StartToDeviceEventContent = serde_json::from_value(content).unwrap(); + let calculated_commitment = calculate_commitment(public_key, &content); + + assert_eq!(commitment, &calculated_commitment); + } + + #[test] + fn emoji_generation() { let bytes = vec![0, 0, 0, 0, 0, 0]; let index: Vec<(&'static str, &'static str)> = vec![0, 0, 0, 0, 0, 0, 0] .into_iter() @@ -516,7 +570,7 @@ mod test { } #[test] - fn test_decimal_generation() { + fn decimal_generation() { let bytes = vec![0, 0, 0, 0, 0]; let result = bytes_to_decimal(bytes); diff --git a/matrix_sdk_crypto/src/verification/sas/sas_state.rs b/matrix_sdk_crypto/src/verification/sas/sas_state.rs index 90966008..ab136cae 100644 --- a/matrix_sdk_crypto/src/verification/sas/sas_state.rs +++ b/matrix_sdk_crypto/src/verification/sas/sas_state.rs @@ -19,7 +19,7 @@ use std::{ time::{Duration, Instant}, }; -use olm_rs::{sas::OlmSas, utility::OlmUtility}; +use olm_rs::sas::OlmSas; use matrix_sdk_common::{ events::{ @@ -40,8 +40,11 @@ use matrix_sdk_common::{ identifiers::{DeviceId, UserId}, uuid::Uuid, }; +use tracing::error; -use super::helpers::{get_decimal, get_emoji, get_mac_content, receive_mac_event, SasIds}; +use super::helpers::{ + calculate_commitment, get_decimal, get_emoji, get_mac_content, receive_mac_event, SasIds, +}; use crate::{ identities::{ReadOnlyDevice, UserIdentities}, @@ -176,7 +179,7 @@ pub struct Started { #[derive(Clone, Debug)] pub struct Accepted { accepted_protocols: Arc, - json_start_content: String, + start_content: Arc, commitment: String, } @@ -348,8 +351,7 @@ impl SasState { let accepted_protocols = AcceptedProtocols::try_from(content.clone()).map_err(|c| self.clone().cancel(c))?; - let json_start_content = serde_json::to_string(&self.as_content()) - .expect("Can't deserialize start event content"); + let start_content = self.as_content().into(); Ok(SasState { inner: self.inner, @@ -358,9 +360,9 @@ impl SasState { creation_time: self.creation_time, last_event_time: self.last_event_time, state: Arc::new(Accepted { - json_start_content, + start_content, commitment: content.commitment.clone(), - accepted_protocols: Arc::new(accepted_protocols), + accepted_protocols: accepted_protocols.into(), }), }) } else { @@ -391,12 +393,14 @@ impl SasState { ) -> Result, SasState> { if let StartMethod::MSasV1(content) = &event.content.method { let sas = OlmSas::new(); - let utility = OlmUtility::new(); - let json_content = - serde_json::to_string(&event.content).expect("Can't serialize content"); let pubkey = sas.public_key(); - let commitment = utility.sha256_utf8_msg(&format!("{}{}", pubkey, json_content)); + let commitment = calculate_commitment(&pubkey, &event.content); + + error!( + "Calculated commitment for pubkey {} and content {:?} {}", + pubkey, event.content, commitment + ); let sas = SasState { inner: Arc::new(Mutex::new(sas)), @@ -540,11 +544,7 @@ impl SasState { self.check_event(&event.sender, &event.content.transaction_id) .map_err(|c| self.clone().cancel(c))?; - let utility = OlmUtility::new(); - let commitment = utility.sha256_utf8_msg(&format!( - "{}{}", - event.content.key, self.state.json_start_content - )); + let commitment = calculate_commitment(&event.content.key, &self.state.start_content); if self.state.commitment != commitment { Err(self.cancel(CancelCode::InvalidMessage))