7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 1 | A no-network-IO implementation of a state machine that handles end-to-end |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 2 | encryption for [Matrix] clients. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 3 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 4 | If you're just trying to write a Matrix client or bot in Rust, you're probably |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 5 | looking for [matrix-sdk] instead. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 6 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 7 | However, if you're looking to add end-to-end encryption to an existing Matrix |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 8 | client or library, read on. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 9 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 10 | The state machine works in a push/pull manner: |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 11 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 12 | - you push state changes and events retrieved from a Matrix homeserver /sync |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 13 | response into the state machine |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 14 | - you pull requests that you'll need to send back to the homeserver out of the |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 15 | state machine |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 16 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 17 | ```rust,no_run |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 18 | use std::collections::BTreeMap; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 19 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 20 | use matrix_sdk_crypto::{ |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 21 | DecryptionSettings, EncryptionSyncChanges, OlmError, OlmMachine, TrustRequirement, |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 22 | }; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 23 | use ruma::{api::client::sync::sync_events::DeviceLists, device_id, user_id}; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 24 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 25 | #[tokio::main] |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 26 | async fn main() -> Result<(), OlmError> { |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 27 | let alice = user_id!("@alice:example.org"); |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 28 | let machine = OlmMachine::new(&alice, device_id!("DEVICEID")).await; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 29 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 30 | let changed_devices = DeviceLists::default(); |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 31 | let one_time_key_counts = BTreeMap::default(); |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 32 | let unused_fallback_keys = Some(Vec::new()); |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 33 | let next_batch_token = "T0K3N".to_owned(); |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 34 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 35 | let decryption_settings = |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 36 | DecryptionSettings { sender_device_trust_requirement: TrustRequirement::Untrusted }; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 37 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 38 | // Push changes that the server sent to us in a sync response. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 39 | let decrypted_to_device = machine |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 40 | .receive_sync_changes( |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 41 | EncryptionSyncChanges { |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 42 | to_device_events: vec![], |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 43 | changed_devices: &changed_devices, |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 44 | one_time_keys_counts: &one_time_key_counts, |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 45 | unused_fallback_keys: unused_fallback_keys.as_deref(), |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 46 | next_batch_token: Some(next_batch_token), |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 47 | }, |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 48 | &decryption_settings, |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 49 | ) |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 50 | .await?; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 51 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 52 | // Pull requests that we need to send out. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 53 | let outgoing_requests = machine.outgoing_requests().await?; |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 54 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 55 | // Send the requests out here and call machine.mark_request_as_sent(). |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 56 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 57 | Ok(()) |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 58 | } |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 59 | ``` |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 60 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 61 | It is recommended to use the [tutorial] to understand how end-to-end encryption |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 62 | works in Matrix and how to add end-to-end encryption support in your Matrix |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 63 | client library. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 64 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 65 | [Matrix]: https://matrix.org/ |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 66 | [matrix-sdk]: https://github.com/matrix-org/matrix-rust-sdk/ |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 67 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 68 | # Crate feature flags |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 69 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 70 | The following crate feature flags are available: |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 71 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 72 | | Feature | Default | Description | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 73 | | --------- | :-----: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 74 | | `qrcode` | No | Enables QR code based interactive verification | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 75 | | `js` | No | Enables JavaScript API usage for things like the current system time on WASM (does nothing on other targets) | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 76 | | `testing` | No | Provides facilities and functions for tests, in particular for integration testing store implementations. ATTENTION: do not ever use outside of tests, we do not provide any stability warantees on these, these are merely helpers. If you find you _need_ any function provided here outside of tests, please open a Github Issue and inform us about your use case for us to consider. | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 77 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 78 | - `testing`: Provides facilities and functions for tests, in particular for |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 79 | integration testing store implementations. ATTENTION: do not ever use outside |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 80 | of tests, we do not provide any stability warantees on these, these are merely |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 81 | helpers. If you find you _need_ any function provided here outside of tests, |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 82 | please open a Github Issue and inform us about your use case for us to |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 83 | consider. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 84 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 85 | - `_disable-minimum-rotation-period-ms`: Do not use except for testing. Disables |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 86 | the floor on the rotation period of room keys. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 87 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 88 | ## Enabling logging |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 89 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 90 | Users of the `matrix-sdk-crypto` crate can enable log output by depending on the |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 91 | `tracing-subscriber` crate and including the following line in their |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 92 | application (e.g. at the start of `main`): |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 93 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 94 | ```no_compile |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 95 | tracing_subscriber::fmt::init(); |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 96 | ``` |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 97 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 98 | The log output is controlled via the `RUST_LOG` environment variable by |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 99 | setting it to one of the `error`, `warn`, `info`, `debug` or `trace` levels. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 100 | The output is printed to stdout. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 101 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 102 | The `RUST_LOG` variable also supports a more advanced syntax for filtering |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 103 | log output more precisely, for instance with crate-level granularity. For |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 104 | more information on this, check out the [tracing-subscriber documentation]. |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 105 | |
7ff8adafe9e4 | atagen | 2026-10-22 12:30 UTC | 106 | [tracing-subscriber documentation]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/ |