matrix_sdk::encryption

Struct Encryption

Source
pub struct Encryption { /* private fields */ }
Available on crate feature e2e-encryption only.
Expand description

A high-level API to manage the client’s encryption.

To get this, use Client::encryption().

Implementations§

Source§

impl Encryption

Source

pub async fn ed25519_key(&self) -> Option<String>

Get the public ed25519 key of our own device. This is usually what is called the fingerprint of the device.

Source

pub async fn curve25519_key(&self) -> Option<Curve25519PublicKey>

Get the public Curve25519 key of our own device.

Source

pub async fn device_creation_timestamp(&self) -> MilliSecondsSinceUnixEpoch

Get the current device creation timestamp.

Source

pub async fn cross_signing_status(&self) -> Option<CrossSigningStatus>

Get the status of the private cross signing keys.

This can be used to check which private cross signing keys we have stored locally.

Source

pub async fn tracked_users( &self, ) -> Result<HashSet<OwnedUserId>, CryptoStoreError>

Get all the tracked users we know about

Tracked users are users for which we keep the device list of E2EE capable devices up to date.

Source

pub fn verification_state(&self) -> Subscriber<VerificationState>

Get a Subscriber for the VerificationState.

§Examples
use matrix_sdk::{encryption, Client};
use url::Url;

let homeserver = Url::parse("http://example.com")?;
let client = Client::new(homeserver).await?;
let mut subscriber = client.encryption().verification_state();

let current_value = subscriber.get();

println!("The current verification state is: {current_value:?}");

if let Some(verification_state) = subscriber.next().await {
    println!("Received verification state update {:?}", verification_state)
}
Source

pub async fn get_verification( &self, user_id: &UserId, flow_id: &str, ) -> Option<Verification>

Get a verification object with the given flow id.

Source

pub async fn get_verification_request( &self, user_id: &UserId, flow_id: impl AsRef<str>, ) -> Option<VerificationRequest>

Get a VerificationRequest object for the given user with the given flow id.

Source

pub async fn get_device( &self, user_id: &UserId, device_id: &DeviceId, ) -> Result<Option<Device>, CryptoStoreError>

Get a specific device of a user.

§Arguments
  • user_id - The unique id of the user that the device belongs to.

  • device_id - The unique id of the device.

Returns a Device if one is found and the crypto store didn’t throw an error.

This will always return None if the client hasn’t been logged in.

§Examples
if let Some(device) =
    client.encryption().get_device(alice, device_id!("DEVICEID")).await?
{
    println!("{:?}", device.is_verified());

    if !device.is_verified() {
        let verification = device.request_verification().await?;
    }
}
Source

pub async fn get_own_device(&self) -> Result<Option<Device>, CryptoStoreError>

A convenience method to retrieve your own device from the store.

This is the same as calling Encryption::get_device() with your own user and device ID.

This will always return a device, unless you are not logged in.

Source

pub async fn get_user_devices( &self, user_id: &UserId, ) -> Result<UserDevices, Error>

Get a map holding all the devices of an user.

This will always return an empty map if the client hasn’t been logged in.

§Arguments
  • user_id - The unique id of the user that the devices belong to.
§Examples
let devices = client.encryption().get_user_devices(alice).await?;

for device in devices.devices() {
    println!("{device:?}");
}
Source

pub async fn get_user_identity( &self, user_id: &UserId, ) -> Result<Option<UserIdentity>, CryptoStoreError>

Get the E2EE identity of a user from the crypto store.

Usually, we only have the E2EE identity of a user locally if the user is tracked, meaning that we are both members of the same encrypted room.

To get the E2EE identity of a user even if it is not available locally use Encryption::request_user_identity().

§Arguments
  • user_id - The unique id of the user that the identity belongs to.

Returns a UserIdentity if one is found and the crypto store didn’t throw an error.

This will always return None if the client hasn’t been logged in.

§Examples
let user = client.encryption().get_user_identity(alice).await?;

if let Some(user) = user {
    println!("{:?}", user.is_verified());

    let verification = user.request_verification().await?;
}
Source

pub async fn request_user_identity( &self, user_id: &UserId, ) -> Result<Option<UserIdentity>>

Get the E2EE identity of a user from the homeserver.

The E2EE identity returned is always guaranteed to be up-to-date. If the E2EE identity is not found, it should mean that the user did not set up cross-signing.

If you want the E2EE identity of a user without making a request to the homeserver, use Encryption::get_user_identity() instead.

§Arguments
  • user_id - The ID of the user that the identity belongs to.

Returns a UserIdentity if one is found. Returns an error if there was an issue with the crypto store or with the request to the homeserver.

This will always return None if the client hasn’t been logged in.

§Examples
let user = client.encryption().request_user_identity(alice).await?;

if let Some(user) = user {
    println!("User is verified: {:?}", user.is_verified());

    let verification = user.request_verification().await?;
}
Source

pub async fn devices_stream(&self) -> Result<impl Stream<Item = DeviceUpdates>>

Returns a stream of device updates, allowing users to listen for notifications about new or changed devices.

The stream produced by this method emits updates whenever a new device is discovered or when an existing device’s information is changed. Users can subscribe to this stream and receive updates in real-time.

§Examples
let devices_stream = client.encryption().devices_stream().await?;
let user_id = client
    .user_id()
    .expect("We should know our user id after we have logged in");
pin_mut!(devices_stream);

for device_updates in devices_stream.next().await {
    if let Some(user_devices) = device_updates.new.get(user_id) {
        for device in user_devices.values() {
            println!("A new device has been added {}", device.device_id());
        }
    }
}
Source

pub async fn user_identities_stream( &self, ) -> Result<impl Stream<Item = IdentityUpdates>>

Returns a stream of user identity updates, allowing users to listen for notifications about new or changed user identities.

The stream produced by this method emits updates whenever a new user identity is discovered or when an existing identities information is changed. Users can subscribe to this stream and receive updates in real-time.

§Examples
let identities_stream =
    client.encryption().user_identities_stream().await?;
pin_mut!(identities_stream);

for identity_updates in identities_stream.next().await {
    for (_, identity) in identity_updates.new {
        println!("A new identity has been added {}", identity.user_id());
    }
}
Source

pub async fn bootstrap_cross_signing( &self, auth_data: Option<AuthData>, ) -> Result<()>

Create and upload a new cross signing identity.

§Arguments
  • auth_data - This request requires user interactive auth, the first request needs to set this to None and will always fail with an UiaaResponse. The response will contain information for the interactive auth and the same request needs to be made but this time with some auth_data provided.
§Examples
if let Err(e) = client.encryption().bootstrap_cross_signing(None).await {
    if let Some(response) = e.as_uiaa_response() {
        let mut password = uiaa::Password::new(
            uiaa::UserIdentifier::UserIdOrLocalpart("example".to_owned()),
            "wordpass".to_owned(),
        );
        password.session = response.session.clone();

        client
            .encryption()
            .bootstrap_cross_signing(Some(uiaa::AuthData::Password(password)))
            .await
            .expect("Couldn't bootstrap cross signing")
    } else {
        panic!("Error during cross signing bootstrap {:#?}", e);
    }
}
Source

pub async fn reset_cross_signing( &self, ) -> Result<Option<CrossSigningResetHandle>>

Reset the cross-signing keys.

§Example
let encryption = client.encryption();

if let Some(handle) = encryption.reset_cross_signing().await? {
    match handle.auth_type() {
        CrossSigningResetAuthType::Uiaa(uiaa) => {
            use matrix_sdk::ruma::api::client::uiaa;

            let password = "1234".to_owned();
            let mut password = uiaa::Password::new(user_id, password);
            password.session = uiaa.session;

            handle.auth(Some(uiaa::AuthData::Password(password))).await?;
        }
        CrossSigningResetAuthType::Oidc(o) => {
            println!(
                "To reset your end-to-end encryption cross-signing identity, \
                you first need to approve it at {}",
                o.approval_url
            );
            handle.auth(None).await?;
        }
    }
}
Source

pub async fn bootstrap_cross_signing_if_needed( &self, auth_data: Option<AuthData>, ) -> Result<()>

Create and upload a new cross signing identity, if that has not been done yet.

This will only create a new cross-signing identity if the user had never done it before. If the user did it before, then this is a no-op.

See also the documentation of Self::bootstrap_cross_signing for the behavior of this function.

§Arguments
  • auth_data - This request requires user interactive auth, the first request needs to set this to None and will always fail with an UiaaResponse. The response will contain information for the interactive auth and the same request needs to be made but this time with some auth_data provided.
§Examples
if let Err(e) = client.encryption().bootstrap_cross_signing_if_needed(None).await {
    if let Some(response) = e.as_uiaa_response() {
        let mut password = uiaa::Password::new(
            uiaa::UserIdentifier::UserIdOrLocalpart("example".to_owned()),
            "wordpass".to_owned(),
        );
        password.session = response.session.clone();

        // Note, on the failed attempt we can use `bootstrap_cross_signing` immediately, to
        // avoid checks.
        client
            .encryption()
            .bootstrap_cross_signing(Some(uiaa::AuthData::Password(password)))
            .await
            .expect("Couldn't bootstrap cross signing")
    } else {
        panic!("Error during cross signing bootstrap {:#?}", e);
    }
}
Source

pub async fn export_room_keys( &self, path: PathBuf, passphrase: &str, predicate: impl FnMut(&InboundGroupSession) -> bool, ) -> Result<()>

Available on non-WebAssembly only.

Export E2EE keys that match the given predicate encrypting them with the given passphrase.

§Arguments
  • path - The file path where the exported key file will be saved.

  • passphrase - The passphrase that will be used to encrypt the exported room keys.

  • predicate - A closure that will be called for every known InboundGroupSession, which represents a room key. If the closure returns true the InboundGroupSessoin will be included in the export, if the closure returns false it will not be included.

§Panics

This method will panic if it isn’t run on a Tokio runtime.

This method will panic if it can’t get enough randomness from the OS to encrypt the exported keys securely.

§Examples
let path = PathBuf::from("/home/example/e2e-keys.txt");
// Export all room keys.
client
    .encryption()
    .export_room_keys(path, "secret-passphrase", |_| true)
    .await?;

// Export only the room keys for a certain room.
let path = PathBuf::from("/home/example/e2e-room-keys.txt");
let room_id = room_id!("!test:localhost");

client
    .encryption()
    .export_room_keys(path, "secret-passphrase", |s| s.room_id() == room_id)
    .await?;
Source

pub async fn import_room_keys( &self, path: PathBuf, passphrase: &str, ) -> Result<RoomKeyImportResult, RoomKeyImportError>

Available on non-WebAssembly only.

Import E2EE keys from the given file path.

§Arguments
  • path - The file path where the exported key file will can be found.

  • passphrase - The passphrase that should be used to decrypt the exported room keys.

Returns a tuple of numbers that represent the number of sessions that were imported and the total number of sessions that were found in the key export.

§Panics

This method will panic if it isn’t run on a Tokio runtime.

let path = PathBuf::from("/home/example/e2e-keys.txt");
let result =
    client.encryption().import_room_keys(path, "secret-passphrase").await?;

println!(
    "Imported {} room keys out of {}",
    result.imported_count, result.total_count
);
Source

pub async fn room_keys_received_stream( &self, ) -> Option<impl Stream<Item = Result<Vec<RoomKeyInfo>, BroadcastStreamRecvError>>>

Receive notifications of room keys being received as a Stream.

Each time a room key is updated in any way, an update will be sent to the stream. Updates that happen at the same time are batched into a Vec.

If the reader of the stream lags too far behind, an error is broadcast containing the number of skipped items.

§Examples
use futures_util::StreamExt;

let Some(mut room_keys_stream) =
    client.encryption().room_keys_received_stream().await
else {
    return Ok(());
};

while let Some(update) = room_keys_stream.next().await {
    println!("Received room keys {update:?}");
}
Source

pub fn secret_storage(&self) -> SecretStorage

Get the secret storage manager of the client.

Source

pub fn backups(&self) -> Backups

Get the backups manager of the client.

Source

pub fn recovery(&self) -> Recovery

Get the recovery manager of the client.

Source

pub async fn enable_cross_process_store_lock( &self, lock_value: String, ) -> Result<(), Error>

Enables the crypto-store cross-process lock.

This may be required if there are multiple processes that may do writes to the same crypto store. In that case, it’s necessary to create a lock, so that only one process writes to it, otherwise this may cause confusing issues because of stale data contained in in-memory caches.

The provided lock_value must be a unique identifier for this process. Check Client::cross_process_store_locks_holder_name to get the global value.

Source

pub async fn spin_lock_store( &self, max_backoff: Option<u32>, ) -> Result<Option<CrossProcessLockStoreGuardWithGeneration>, Error>

If a lock was created with Self::enable_cross_process_store_lock, spin-waits until the lock is available.

May reload the OlmMachine, after obtaining the lock but not on the first time.

Source

pub async fn try_lock_store_once( &self, ) -> Result<Option<CrossProcessLockStoreGuardWithGeneration>, Error>

If a lock was created with Self::enable_cross_process_store_lock, attempts to lock it once.

Returns a guard to the lock, if it was obtained.

Source

pub async fn wait_for_e2ee_initialization_tasks(&self)

Waits for end-to-end encryption initialization tasks to finish, if any was running in the background.

Trait Implementations§

Source§

impl Clone for Encryption

Source§

fn clone(&self) -> Encryption

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Encryption

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T> CompatExt for T

§

fn compat(self) -> Compat<T>

Applies the [Compat] adapter by value. Read more
§

fn compat_ref(&self) -> Compat<&T>

Applies the [Compat] adapter by shared reference. Read more
§

fn compat_mut(&mut self) -> Compat<&mut T>

Applies the [Compat] adapter by mutable reference. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T, UT> HandleAlloc<UT> for T
where T: Send + Sync,

Source§

fn new_handle(value: Arc<T>) -> Handle

Create a new handle for an Arc value Read more
Source§

fn clone_handle(handle: Handle) -> Handle

Clone a handle Read more
Source§

fn consume_handle(handle: Handle) -> Arc<T>

Consume a handle, getting back the initial Arc<>
Source§

fn get_arc(handle: Handle) -> Arc<Self>

Get a clone of the Arc<> using a “borrowed” handle. Read more
Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<T> Any for T
where T: Any,

Source§

impl<T> AsyncTraitDeps for T

Source§

impl<T> CloneAny for T
where T: Any + Clone,

Source§

impl<T> CloneAnySend for T
where T: Any + Send + Clone,

Source§

impl<T> CloneAnySendSync for T
where T: Any + Send + Sync + Clone,

Source§

impl<T> CloneAnySync for T
where T: Any + Sync + Clone,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T

Source§

impl<T> SendOutsideWasm for T
where T: Send,

Source§

impl<T> SyncOutsideWasm for T
where T: Sync,