libsignal_protocol/
lib.rs

1//! A Rust interface to the [libsignal-protocol-c] library.
2//!
3//! A ratcheting forward secrecy protocol that works in synchronous and
4//! asynchronous messaging environments.
5//!
6//! # Key Concepts
7//!
8//! ## PreKeys
9//!
10//! This protocol uses a concept called "*PreKeys*". A PreKey is a
11//! [`keys::PublicKey`] and an associated unique ID which are stored together by
12//! a server. PreKeys can also be signed.
13//!
14//! At install time, clients generate a single signed PreKey, as well as a large
15//! list of unsigned PreKeys, and transmit all of them to the server.
16//!
17//! ## Sessions
18//!
19//! The Signal Protocol is session-oriented. Clients establish a "session"
20//! which is then used for all subsequent encrypt/decrypt operations. There is
21//! no need to ever tear down a session once one has been established.
22//!
23//! Sessions are established in one of three ways:
24//!
25//! 1. [`PreKeyBundle`]. A client that wishes to send a message to a recipient
26//!    can establish a session by retrieving a [`PreKeyBundle`] for that
27//!    recipient from the server.
28//! 2. [`PreKeySignalMessage`]s.  A client can receive a [`PreKeySignalMessage`]
29//!    from a recipient and use it to establish a session.
30//! 3. KeyExchangeMessages. Two clients can exchange KeyExchange messages to
31//!    establish a session.
32//!
33//! ## State
34//!
35//! An established session encapsulates a lot of state between two clients. That
36//! state is maintained in durable records which need to be kept for the life of
37//! the session.
38//!
39//! State is kept in the following places:
40//!
41//! 1. Identity State. Clients will need to maintain the state of their own
42//!    identity key pair, as well as identity keys received from other clients
43//!    (saved in an [`IdentityKeyStore`]).
44//! 1. PreKey State. Clients will need to maintain the state of their generated
45//!    PreKeys in a [`PreKeyStore`].
46//! 1. Signed PreKey States. Clients will need to maintain the state of their
47//!    signed PreKeys using a [`SignedPreKeyStore`].
48//! 1. Session State. Clients will need to maintain the state of the sessions
49//!    they have established using a [`SessionStore`].
50//!
51//! [libsignal-protocol-c]: https://github.com/signalapp/libsignal-protocol-c
52
53#![deny(
54    missing_docs,
55    missing_debug_implementations,
56    missing_copy_implementations,
57    elided_lifetimes_in_paths,
58    rust_2018_idioms,
59    clippy::cargo_common_metadata,
60    clippy::fallible_impl_from,
61    clippy::missing_const_for_fn,
62    intra_doc_link_resolution_failure
63)]
64
65// we use the *-sys crate everywhere so give it a shorter name
66#[allow(unused_extern_crates)]
67extern crate libsignal_protocol_sys as sys;
68#[cfg(feature = "crypto-openssl")]
69#[macro_use]
70extern crate rental;
71
72use std::io::Write;
73
74use failure::Error;
75
76pub use crate::{
77    address::Address,
78    buffer::Buffer,
79    context::*,
80    errors::{FromInternalErrorCode, InternalError, IntoInternalErrorCode},
81    hkdf::HMACBasedKeyDerivationFunction,
82    pre_key_bundle::{PreKeyBundle, PreKeyBundleBuilder},
83    session_builder::SessionBuilder,
84    session_cipher::SessionCipher,
85    session_record::SessionRecord,
86    session_state::SessionState,
87    store_context::StoreContext,
88};
89// bring into scope for rustdoc
90#[allow(unused_imports)]
91use crate::messages::PreKeySignalMessage;
92// so rustdoc can resolve links
93#[allow(unused_imports)]
94use crate::stores::{
95    IdentityKeyStore, PreKeyStore, SessionStore, SignedPreKeyStore,
96};
97
98#[macro_use]
99mod macros;
100
101mod address;
102mod buffer;
103mod context;
104pub mod crypto;
105mod errors;
106mod hkdf;
107pub mod keys;
108pub mod messages;
109mod pre_key_bundle;
110pub(crate) mod raw_ptr;
111mod session_builder;
112mod session_cipher;
113mod session_record;
114mod session_state;
115mod store_context;
116pub mod stores;
117
118/// A helper trait for something which can be serialized to protobufs.
119pub trait Serializable {
120    /// Serialize the object to a buffer.
121    fn serialize(&self) -> Result<Buffer, Error>;
122
123    /// Parse the provided data in the protobuf format.
124    fn deserialize(data: &[u8]) -> Result<Self, Error>
125    where
126        Self: Sized;
127
128    /// Helper for serializing to anything which implements [`Write`].
129    fn serialize_to<W: Write>(&self, mut writer: W) -> Result<(), Error> {
130        let buffer = self.serialize()?;
131        writer.write_all(buffer.as_slice())?;
132
133        Ok(())
134    }
135}