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}