@@ -112,8 +112,21 @@ pub mod vodozemac {
112
112
/// A step by step guide that explains how to include [end-to-end-encryption]
113
113
/// support in a [Matrix] client library.
114
114
///
115
- /// If you're not familiar with Matrix or how clients communicate with a Matrix
116
- /// homeserver it's advised to get yourself familiar with the [client-server spec](https://matrix.org/docs/spec/client_server/).
115
+ /// This crate implements a [sans-network-io](https://sans-io.readthedocs.io/)
116
+ /// state machine that allows you to add [end-to-end-encryption] support to a
117
+ /// [Matrix] client library.
118
+ ///
119
+ /// This guide aims to provide a comprehensive understanding of end-to-end
120
+ /// encryption in Matrix without any prior knowledge requirements. However, it
121
+ /// is recommended that the reader has a basic understanding of Matrix and its
122
+ /// [client-server specification] for a more informed and efficient learning
123
+ /// experience.
124
+ ///
125
+ /// The [introductory](#introduction) section provides a simplified explanation
126
+ /// of end-to-end encryption and its implementation in Matrix for those who may
127
+ /// not have prior knowledge. If you already have a solid understanding of
128
+ /// end-to-end encryption, including the [Olm] and [Megolm] protocols, you may
129
+ /// choose to skip directly to the [Getting Started](#getting-started) section.
117
130
///
118
131
/// # Table of contents
119
132
/// 1. [Introduction](#introduction)
@@ -124,9 +137,20 @@ pub mod vodozemac {
124
137
///
125
138
/// # Introduction
126
139
///
127
- /// This crate implements a [sans-network-io](https://sans-io.readthedocs.io/) state machine that
128
- /// allows you to add [end-to-end-encryption] support to a [Matrix] client
129
- /// library.
140
+ /// Welcome to the first part of this guide, where we will introduce the
141
+ /// fundamental concepts of end-to-end encryption and its implementation in
142
+ /// Matrix.
143
+ ///
144
+ /// This section will provide a clear and concise overview of what
145
+ /// end-to-end encryption is and why it is important for secure communication.
146
+ /// You will also learn about how Matrix uses end-to-end encryption to protect
147
+ /// the privacy and security of its users' communications. Whether you are new
148
+ /// to the topic or simply want to improve your understanding, this section will
149
+ /// serve as a solid foundation for the rest of the guide.
150
+ ///
151
+ /// Let's dive in!
152
+ ///
153
+ /// ## Notation
130
154
///
131
155
/// ## End-to-end-encryption
132
156
///
@@ -143,7 +167,7 @@ pub mod vodozemac {
143
167
/// flowchart LR
144
168
/// alice[Alice]
145
169
/// bob[Bob]
146
- /// subgraph Server
170
+ /// subgraph Homeserver
147
171
/// direction LR
148
172
/// outbox[Alice outbox]
149
173
/// inbox[Bob inbox]
@@ -161,7 +185,7 @@ pub mod vodozemac {
161
185
/// flowchart LR
162
186
/// alice[Alice]
163
187
/// bob[Bob]
164
- /// subgraph Server
188
+ /// subgraph Homeserver
165
189
/// direction LR
166
190
/// outbox[Alice outbox]
167
191
/// inbox[Bob inbox]
@@ -174,6 +198,10 @@ pub mod vodozemac {
174
198
///
175
199
/// Note that the path from the outbox to the inbox is now encrypted as well.
176
200
///
201
+ /// Alice and Bob have created a secure communication channel
202
+ /// through which they can exchange messages confidentially, without the risk of
203
+ /// the server accessing the contents of their messages.
204
+ ///
177
205
/// ## Publishing cryptographic identities of devices
178
206
///
179
207
/// If Alice and Bob want to establish a secure channel over which they can
@@ -192,13 +220,10 @@ pub mod vodozemac {
192
220
/// the directory to find the public key of the user they wish to communicate
193
221
/// with, and download it to their own device.
194
222
///
195
- /// Once a user has the other user's public key, they can use it to establish an
196
- /// end-to-end encrypted channel using a [key-agreement] protocol.
197
- ///
198
223
/// ```mermaid
199
224
/// flowchart LR
200
225
/// alice[Alice]
201
- /// subgraph server[Server ]
226
+ /// subgraph homeserver[Homeserver ]
202
227
/// direction LR
203
228
/// directory[(Public key directory)]
204
229
/// end
@@ -208,6 +233,45 @@ pub mod vodozemac {
208
233
/// directory -- download keys --> bob
209
234
/// ```
210
235
///
236
+ /// Once a user has the other user's public key, they can use it to establish an
237
+ /// end-to-end encrypted channel using a [key-agreement] protocol.
238
+ ///
239
+ /// ## Using the Triple Diffie-Hellman key-agreement protocol
240
+ ///
241
+ /// In X3DH, each user generates a long-term identity key pair and a set of
242
+ /// one-time prekeys. When two users want to establish a shared secret key, they
243
+ /// exchange their public identity keys and one of their prekeys. These public
244
+ /// keys are then used in a [Diffie-Hellman] key exchange to compute a shared
245
+ /// secret key.
246
+ ///
247
+ /// The use of one-time prekeys ensures that the shared secret key is different
248
+ /// for each session, even if the same identity keys are used.
249
+ ///
250
+ /// ```mermaid
251
+ /// flowchart LR
252
+ /// subgraph alice_keys[Alice Keys]
253
+ /// direction TB
254
+ /// alice_key[Alice's identity key]
255
+ /// alice_base_key[Alice's one-time key]
256
+ /// end
257
+ ///
258
+ /// subgraph bob_keys[Bob Keys]
259
+ /// direction TB
260
+ /// bob_key[Bob's identity key]
261
+ /// bob_one_time[Bob's one-time key]
262
+ /// end
263
+ ///
264
+ /// alice_key <--> bob_one_time
265
+ /// alice_base_key <--> bob_one_time
266
+ /// alice_base_key <--> bob_key
267
+ /// ```
268
+ ///
269
+ /// Similar to [X3DH] (Extended Triple Diffie-Hellman) key agreement protocol
270
+ ///
271
+ /// ## Speeding up encryption for large groups
272
+ ///
273
+ /// TODO Explain how megolm fits into this
274
+ ///
211
275
/// # Getting started
212
276
///
213
277
/// In the [Matrix] world the server is called a [homeserver]
@@ -261,13 +325,27 @@ pub mod vodozemac {
261
325
///
262
326
/// # Decryption
263
327
///
328
+ /// In the world of encrypted communication, it is common to start with the
329
+ /// encryption step when implementing a protocol. However, in the case of adding
330
+ /// end-to-end encryption support to a Matrix client library, a simpler approach
331
+ /// is to first focus on the decryption process. This is because there are
332
+ /// already Matrix clients in existence that support encryption, which means
333
+ /// that our client library can simply receive encrypted messages and then
334
+ /// decrypt them.
335
+ ///
336
+ /// In this section, we will guide you through the minimal steps
337
+ /// necessary to get the decryption process up and running using the
338
+ /// matrix-sdk-crypto Rust crate. By the end of this section you should have a
339
+ /// Matrix client that is able to decrypt room events that other clients have
340
+ /// sent.
341
+ ///
264
342
/// To enable decryption the following three steps are needed:
265
343
///
266
344
/// 1. [The cryptographic identity of your device needs to be published to the
267
- /// homeserver](#uploading-identity-and-one-time-key)
345
+ /// homeserver](#uploading-identity-and-one-time-keys).
268
346
/// 2. [Decryption keys coming in from other devices need to be processed and
269
- /// stored](#receiving-room-keys-and-related-changes)
270
- /// 3. [Messages need to be decrypted](#decrypting-room-events)
347
+ /// stored](#receiving-room-keys-and-related-changes).
348
+ /// 3. [Individual messages need to be decrypted](#decrypting-room-events).
271
349
///
272
350
/// The simplified flowchart
273
351
/// ```mermaid
@@ -285,7 +363,16 @@ pub mod vodozemac {
285
363
///
286
364
/// ## Uploading identity and one-time keys.
287
365
///
288
- /// TODO
366
+ /// The first step is to announce the support for it to other users in the
367
+ /// Matrix network. This involves publishing your long-term device keys and a
368
+ /// set of one-time prekeys to the homeserver. This information is used by other
369
+ /// devices to encrypt messages specifically for your device.
370
+ ///
371
+ /// To achieve this, you will need to extract any requests that need to be sent
372
+ /// to the homeserver from the [`OlmMachine`] and send them to the homeserver.
373
+ /// The following snipped showcases how to achieve this using the
374
+ /// [`OlmMachine::outgoing_requests()`] method:
375
+ ///
289
376
/// ```no_run
290
377
/// # use std::collections::BTreeMap;
291
378
/// # use ruma::api::client::keys::upload_keys::v3::Response;
@@ -303,6 +390,7 @@ pub mod vodozemac {
303
390
///
304
391
/// // Send each request to the server and push the response into the state machine.
305
392
/// for request in outgoing_requests {
393
+ /// // You can safely send out these requests out in parallel.
306
394
/// let request_id = request.request_id();
307
395
/// let response = send_request(request).await?;
308
396
/// machine.mark_request_as_sent(&request_id, &response).await?;
@@ -313,8 +401,6 @@ pub mod vodozemac {
313
401
///
314
402
/// ## Receiving room keys and related changes
315
403
///
316
- /// TODO
317
- ///
318
404
/// ```no_run
319
405
/// # use std::collections::BTreeMap;
320
406
/// # use anyhow::Result;
@@ -341,6 +427,15 @@ pub mod vodozemac {
341
427
///
342
428
/// ## Decrypting room events
343
429
///
430
+ /// The final step in the decryption process is to decrypt the room events that
431
+ /// are received from the server. To do this, the encrypted events must be
432
+ /// passed to the [`OlmMachine`], which will use the keys that were previously
433
+ /// exchanged between devices to decrypt the events. The decrypted events can
434
+ /// then be processed and displayed to the user in the Matrix client.
435
+ ///
436
+ /// Room events can be decrypted using the [`OlmMachine::decrypt_room_event()`]
437
+ /// method.
438
+ ///
344
439
/// ```no_run
345
440
/// # use std::collections::BTreeMap;
346
441
/// # use anyhow::Result;
@@ -465,6 +560,21 @@ pub mod vodozemac {
465
560
/// ```
466
561
///
467
562
/// ## Encrypting room events
563
+ ///
564
+ /// ```no_run
565
+ /// # use anyhow::Result;
566
+ /// # use matrix_sdk_crypto::OlmMachine;
567
+ /// # #[tokio::main]
568
+ /// # async fn main() -> Result<()> {
569
+ /// # let room_id = unimplemented!();
570
+ /// # let event = unimplemented!();
571
+ /// # let machine: OlmMachine = unimplemented!();
572
+ /// // Decrypt each room event you'd like to display to the user using this method.
573
+ /// let decrypted = machine.decrypt_room_event(event, room_id)?;
574
+ /// # Ok(())
575
+ /// # }
576
+ /// ```
577
+
468
578
///
469
579
/// TODO
470
580
///
@@ -474,10 +584,15 @@ pub mod vodozemac {
474
584
/// TODO
475
585
///
476
586
/// [Matrix]: https://matrix.org/
587
+ /// [Olm]: https://gitlab.matrix.org/matrix-org/olm/-/blob/master/docs/olm.md
588
+ /// [Diffie-Hellman]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
589
+ /// [Megolm]: https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md
477
590
/// [end-to-end-encryption]: https://en.wikipedia.org/wiki/End-to-end_encryption
478
591
/// [homeserver]: https://spec.matrix.org/unstable/#architecture
479
592
/// [key-agreement]: https://en.wikipedia.org/wiki/Key-agreement_protocol
593
+ /// [client-server specification]: https://matrix.org/docs/spec/client_server/
594
+ /// [forward secrecy]: https://en.wikipedia.org/wiki/Forward_secrecy
595
+ /// [replay attacks]: https://en.wikipedia.org/wiki/Replay_attack
480
596
///
481
597
/// [X3DH]: https://signal.org/docs/specifications/x3dh/
482
- /// [diffie-hellman]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
483
598
pub mod tutorial { }
0 commit comments