pub struct Encryption { /* private fields */ }
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
impl Encryption
Sourcepub async fn ed25519_key(&self) -> Option<String>
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.
Sourcepub async fn curve25519_key(&self) -> Option<Curve25519PublicKey>
pub async fn curve25519_key(&self) -> Option<Curve25519PublicKey>
Get the public Curve25519 key of our own device.
Sourcepub async fn device_creation_timestamp(&self) -> MilliSecondsSinceUnixEpoch
pub async fn device_creation_timestamp(&self) -> MilliSecondsSinceUnixEpoch
Get the current device creation timestamp.
Sourcepub async fn cross_signing_status(&self) -> Option<CrossSigningStatus>
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.
Sourcepub async fn tracked_users(
&self,
) -> Result<HashSet<OwnedUserId>, CryptoStoreError>
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.
Sourcepub fn verification_state(&self) -> Subscriber<VerificationState>
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)
}
Sourcepub async fn get_verification(
&self,
user_id: &UserId,
flow_id: &str,
) -> Option<Verification>
pub async fn get_verification( &self, user_id: &UserId, flow_id: &str, ) -> Option<Verification>
Get a verification object with the given flow id.
Sourcepub async fn get_verification_request(
&self,
user_id: &UserId,
flow_id: impl AsRef<str>,
) -> Option<VerificationRequest>
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.
Sourcepub async fn get_device(
&self,
user_id: &UserId,
device_id: &DeviceId,
) -> Result<Option<Device>, CryptoStoreError>
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?;
}
}
Sourcepub async fn get_own_device(&self) -> Result<Option<Device>, CryptoStoreError>
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.
Sourcepub async fn get_user_devices(
&self,
user_id: &UserId,
) -> Result<UserDevices, Error>
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:?}");
}
Sourcepub async fn get_user_identity(
&self,
user_id: &UserId,
) -> Result<Option<UserIdentity>, CryptoStoreError>
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?;
}
Sourcepub async fn request_user_identity(
&self,
user_id: &UserId,
) -> Result<Option<UserIdentity>>
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?;
}
Sourcepub async fn devices_stream(&self) -> Result<impl Stream<Item = DeviceUpdates>>
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());
}
}
}
Sourcepub async fn user_identities_stream(
&self,
) -> Result<impl Stream<Item = IdentityUpdates>>
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());
}
}
Sourcepub async fn bootstrap_cross_signing(
&self,
auth_data: Option<AuthData>,
) -> Result<()>
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 toNone
and will always fail with anUiaaResponse
. The response will contain information for the interactive auth and the same request needs to be made but this time with someauth_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);
}
}
Sourcepub async fn reset_cross_signing(
&self,
) -> Result<Option<CrossSigningResetHandle>>
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?;
}
}
}
Sourcepub async fn bootstrap_cross_signing_if_needed(
&self,
auth_data: Option<AuthData>,
) -> Result<()>
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 toNone
and will always fail with anUiaaResponse
. The response will contain information for the interactive auth and the same request needs to be made but this time with someauth_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);
}
}
Sourcepub async fn export_room_keys(
&self,
path: PathBuf,
passphrase: &str,
predicate: impl FnMut(&InboundGroupSession) -> bool,
) -> Result<()>
Available on non-WebAssembly only.
pub async fn export_room_keys( &self, path: PathBuf, passphrase: &str, predicate: impl FnMut(&InboundGroupSession) -> bool, ) -> Result<()>
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 knownInboundGroupSession
, which represents a room key. If the closure returnstrue
theInboundGroupSessoin
will be included in the export, if the closure returnsfalse
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?;
Sourcepub async fn import_room_keys(
&self,
path: PathBuf,
passphrase: &str,
) -> Result<RoomKeyImportResult, RoomKeyImportError>
Available on non-WebAssembly only.
pub async fn import_room_keys( &self, path: PathBuf, passphrase: &str, ) -> Result<RoomKeyImportResult, RoomKeyImportError>
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
);
Sourcepub async fn room_keys_received_stream(
&self,
) -> Option<impl Stream<Item = Result<Vec<RoomKeyInfo>, BroadcastStreamRecvError>>>
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:?}");
}
Sourcepub fn secret_storage(&self) -> SecretStorage
pub fn secret_storage(&self) -> SecretStorage
Get the secret storage manager of the client.
Sourcepub async fn enable_cross_process_store_lock(
&self,
lock_value: String,
) -> Result<(), Error>
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.
Sourcepub async fn spin_lock_store(
&self,
max_backoff: Option<u32>,
) -> Result<Option<CrossProcessLockStoreGuardWithGeneration>, Error>
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.
Sourcepub async fn try_lock_store_once(
&self,
) -> Result<Option<CrossProcessLockStoreGuardWithGeneration>, Error>
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.
Sourcepub async fn wait_for_e2ee_initialization_tasks(&self)
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
impl Clone for Encryption
Source§fn clone(&self) -> Encryption
fn clone(&self) -> Encryption
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreAuto Trait Implementations§
impl Freeze for Encryption
impl !RefUnwindSafe for Encryption
impl Send for Encryption
impl Sync for Encryption
impl Unpin for Encryption
impl !UnwindSafe for Encryption
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> CompatExt for T
impl<T> CompatExt for T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T, UT> HandleAlloc<UT> for T
impl<T, UT> HandleAlloc<UT> for T
Source§fn consume_handle(handle: Handle) -> Arc<T>
fn consume_handle(handle: Handle) -> Arc<T>
Arc<>
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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