vodozemac/olm/mod.rs
1// Copyright 2021 The Matrix.org Foundation C.I.C.
2// Copyright 2021 Damir Jelić, Denis Kasak
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! An implementation of the Olm double ratchet.
17//!
18//! ## Overview
19//!
20//! The core component of the crate is the [`Account`], representing a single
21//! Olm participant. An Olm [`Account`] consists of a collection of key pairs,
22//! though often documentation will shorten this to just "keys". These are:
23//!
24//! 1. An Ed25519 *signing key pair* representing the stable cryptographic
25//! identity of the participant (the participant's "fingerprint").
26//! 2. A Curve25519 *sender key pair* (also sometimes called the *identity key
27//! pair*, somewhat confusingly).
28//! 3. A number of one-time key pairs.
29//! 4. A current and previous (if any) "fallback" key pair.
30//!
31//! While the key in 1 is used for signing but not encryption, the keys in 2-4
32//! participate in a triple Diffie-Hellman key exchange (3DH) with another Olm
33//! participant, thereby establishing an Olm session on each side of the
34//! communication channel. Ultimately, this session is used for deriving the
35//! concrete encryption keys for a particular message.
36//!
37//! Olm sessions are represented by the [`Session`] struct. Such a session is
38//! created by calling [`Account::create_outbound_session`] on one of the
39//! participating accounts, passing it the Curve25519 sender key and one
40//! Curve25519 one-time key of the other side. The protocol is asynchronous, so
41//! the participant can start sending messages to the other side even before the
42//! other side has created a session, producing so-called pre-key messages (see
43//! [`PreKeyMessage`]).
44//!
45//! Once the other participant receives such a pre-key message, they can create
46//! their own matching session by calling [`Account::create_inbound_session`]
47//! and passing it the pre-key message they received and the Curve25519 sender
48//! key of the other side. This completes the establishment of the Olm
49//! communication channel.
50//!
51//! ```
52//! use anyhow::Result;
53//! use vodozemac::olm::{Account, InboundCreationResult, OlmMessage, SessionConfig};
54//!
55//! fn main() -> Result<()> {
56//! let alice = Account::new();
57//! let mut bob = Account::new();
58//!
59//! bob.generate_one_time_keys(1);
60//! let bob_otk = *bob.one_time_keys().values().next().unwrap();
61//!
62//! let mut alice_session = alice
63//! .create_outbound_session(SessionConfig::version_2(), bob.curve25519_key(), bob_otk);
64//!
65//! bob.mark_keys_as_published();
66//!
67//! let message = "Keep it between us, OK?";
68//! let alice_msg = alice_session.encrypt(message);
69//!
70//! if let OlmMessage::PreKey(m) = alice_msg.clone() {
71//! let result = bob.create_inbound_session(alice.curve25519_key(), &m)?;
72//!
73//! let mut bob_session = result.session;
74//! let what_bob_received = result.plaintext;
75//!
76//! assert_eq!(alice_session.session_id(), bob_session.session_id());
77//!
78//! assert_eq!(message.as_bytes(), what_bob_received);
79//!
80//! let bob_reply = "Yes. Take this, it's dangerous out there!";
81//! let bob_encrypted_reply = bob_session.encrypt(bob_reply).into();
82//!
83//! let what_alice_received = alice_session
84//! .decrypt(&bob_encrypted_reply)?;
85//! assert_eq!(what_alice_received, bob_reply.as_bytes());
86//! }
87//!
88//! Ok(())
89//! }
90//! ```
91//!
92//! ## Sending messages
93//!
94//! To encrypt a message, just call [`Session::encrypt()`]. This will
95//! either produce an [`OlmMessage::PreKey`] or [`OlmMessage::Normal`]
96//! depending on whether the session is fully established. A session is fully
97//! established once you receive (and decrypt) at least one message from the
98//! other side.
99
100mod account;
101mod messages;
102pub(crate) mod session;
103mod session_config;
104mod session_keys;
105mod shared_secret;
106
107pub use account::{
108 Account, AccountPickle, IdentityKeys, InboundCreationResult, OneTimeKeyGenerationResult,
109 SessionCreationError,
110};
111pub use messages::{Message, MessageType, OlmMessage, PreKeyMessage};
112pub use session::{ratchet::RatchetPublicKey, DecryptionError, Session, SessionPickle};
113pub use session_config::SessionConfig;
114pub use session_keys::SessionKeys;