Double Ratchet Algorithm
The Double Ratchet Algorithm is a cryptographic protocol that enables two parties to derive a sequence of unique symmetric keys for encrypting and authenticating messages, starting from an initial shared secret established via a key agreement mechanism such as X3DH or PQXDH.[1] It achieves this through a combination of symmetric key derivation and asynchronous Diffie-Hellman exchanges, ensuring that each message uses a fresh, unpredictable key while maintaining security even in asynchronous communication scenarios.[1]
Developed by Moxie Marlinspike and Trevor Perrin in 2013 as a core component of the Signal Protocol, the algorithm builds on concepts from the Off-the-Record (OTR) messaging protocol to address limitations in prior ratcheting schemes.[2] It is employed in the Signal messaging application to provide end-to-end encryption for text, voice, and video communications.[1] The protocol's design emphasizes forward secrecy, meaning that the compromise of a session key or long-term private keys does not reveal the content of previously exchanged messages, as each message key is derived independently and discarded after use.[1] Additionally, it offers break-in recovery (or post-compromise security), allowing the parties to restore security for future messages after a key compromise, provided that at least one additional Diffie-Hellman exchange occurs subsequently to inject fresh entropy.[1]
At its heart, the Double Ratchet consists of three interconnected key derivation function (KDF) chains: a root chain that manages the overall session state, a sending chain for the sender's message keys, and a receiving chain for decryption.[1] The symmetric-key ratchet advances these chains sequentially with each message sent or received, using a one-way KDF (typically HKDF with HMAC-SHA-256) to generate the next key while rendering prior keys computationally infeasible to reverse.[1] Interleaved with this is the Diffie-Hellman ratchet, which periodically updates the root key by computing a Diffie-Hellman shared secret from one party's private ratchet key and the other's public ratchet key, included in message headers; this asymmetric step ensures security against device compromises and supports asynchronous key updates.[1] These mechanisms together produce message keys that are indistinguishable from random to an adversary lacking the current chain keys, as proven under standard assumptions for the underlying primitives.[3]
The algorithm's resilience has been formally analyzed in subsequent cryptographic research, confirming its security bounds against key compromise impersonation attacks and multi-user extensions, with tightness results establishing that its security loss scales linearly with the number of messages rather than exponentially.[4] Since its introduction, the Double Ratchet has influenced secure messaging standards, including implementations in applications like WhatsApp and Google Messages, though its primary documentation and reference remain tied to Signal's open-source specifications.[1] A revision of the specification published on November 4, 2025, incorporates post-quantum extensions using ML-KEM-based key exchanges to address quantum threats.[2] Ongoing work focuses on further post-quantum adaptations.
History and Development
Origins and Evolution
The Double Ratchet Algorithm originated in 2013 as part of the Signal Protocol, developed by Trevor Perrin and Moxie Marlinspike at Open Whisper Systems (now the Signal Foundation). Initially named the Axolotl Ratchet, it was designed to enable secure, asynchronous messaging with strong encryption properties. The protocol's core ideas were introduced in a November 2013 blog post by Marlinspike, which outlined an advanced ratcheting mechanism for instant messaging applications.[5][1]
The algorithm evolved from earlier cryptographic protocols, incorporating the Diffie-Hellman (DH) ratchet concept from the Off-the-Record (OTR) messaging protocol, originally proposed by Nikita Borisov, Ian Goldberg, and Eric Brewer in 2004, to provide forward secrecy through ephemeral key exchanges. It also drew on symmetric-key ratcheting techniques from protocols like the Silent Circle Instant Messaging Protocol (SCIMP) from 2012 and MinimaLT, to enable efficient key derivation for message encryption. This combination addressed limitations in prior systems, particularly by supporting asynchronous ratcheting that allows users to communicate even when offline, deriving new keys independently for sending and receiving chains.[1]
Key milestones in its development include the open-sourcing of the initial Signal Protocol implementation in 2013 alongside the TextSecure app, making the code publicly available on GitHub for community review and adoption. In February 2014, Open Whisper Systems released TextSecure v2, integrating the Axolotl Ratchet to provide end-to-end encryption for asynchronous instant messaging, marking the protocol's first widespread deployment and transitioning the app from SMS dependency.[6]
The protocol underwent a significant update in March 2016, when Open Whisper Systems renamed the overall framework from Axolotl to the Signal Protocol and specifically rebranded the ratchet mechanism as the Double Ratchet Algorithm to clarify its dual structure of symmetric and asymmetric ratchets, reducing confusion between the key management component and the full protocol. Later that year, in November 2016, Perrin published the formal specification of the Double Ratchet Algorithm, which has since served as the authoritative reference for implementations and influenced standards efforts, including references in IETF Messaging Layer Security (MLS) drafts.[7][2] The specification continued to evolve, with a major revision in November 2025 incorporating post-quantum extensions such as the Sparse Post-Quantum Ratchet and Triple Ratchet for enhanced resistance to quantum computing threats.[2]
Key Contributors
The Double Ratchet Algorithm was primarily designed by Trevor Perrin and Moxie Marlinspike in 2013 as part of the cryptographic protocol for the TextSecure messaging application, now known as Signal.[1] Perrin, a cryptographer and protocol designer, led the development of the ratchet mechanics, focusing on combining symmetric-key and Diffie-Hellman ratcheting to achieve forward secrecy and post-compromise security in asynchronous messaging scenarios.[1] His contributions included specifying the key derivation functions and message key generation processes that form the core of the algorithm's security model.[1]
Moxie Marlinspike, founder of Open Whisper Systems (later rebranded as Signal Messenger), played a pivotal role in integrating the Double Ratchet into mobile messaging protocols, emphasizing practical usability alongside cryptographic strength.[8] Marlinspike's work extended the algorithm's application within the broader Signal Protocol, ensuring seamless end-to-end encryption for real-time conversations while prioritizing user-friendly features like automatic key updates.[1] Open Whisper Systems, established by Marlinspike in 2013, implemented and open-sourced the protocol that year, releasing the TextSecure codebase under a free software license to foster widespread adoption and scrutiny.[8]
The algorithm draws significant influence from earlier work on the Off-the-Record (OTR) messaging protocol, particularly the Diffie-Hellman ratchet concept introduced by Ian Goldberg, Nikita Borisov, and Eric Brewer in their 2004 paper.[1][9] Goldberg, a prominent cryptographer and OTR co-creator, contributed foundational ideas on deniability and forward secrecy through ratcheting, which Perrin and Marlinspike adapted and extended for the Double Ratchet's dual-ratchet structure.[1][9]
Post-2016, the Internet Engineering Task Force (IETF) Messaging Layer Security (MLS) working group built upon the Double Ratchet by developing ratchet trees for group messaging, standardizing extensions that enable scalable key agreement among multiple parties while preserving core security properties.[10] The MLS protocol, formalized in RFC 9420, incorporates asynchronous ratcheting mechanisms inspired by the Double Ratchet to support forward secrecy in dynamic groups.[10]
Community contributions have further refined and disseminated the algorithm through open-source implementations on platforms like GitHub, including Perrin's reference repository and associated wiki, which document variations, audits, and integrations.[11] These efforts, involving developers from various projects, have facilitated peer review and adaptations in diverse cryptographic libraries.[11]
Overview and Design Principles
Core Objectives
The Double Ratchet Algorithm primarily aims to provide end-to-end encryption for messaging protocols, ensuring that communications remain confidential and accessible only to the intended recipients through the use of a shared secret key derived from an initial key agreement.[2] A key objective is achieving forward secrecy (FS), which protects past messages from decryption even if long-term keys or session states are compromised at a later time, by generating ephemeral keys for each message exchange.[2] Additionally, the algorithm seeks post-compromise security (PCS), enabling the recovery of secure communication after a key compromise without permanently undermining future sessions, thus limiting the attacker's ability to access subsequent messages beyond a bounded period.[12]
To support real-world messaging scenarios, the Double Ratchet facilitates asynchronous communication, allowing secure exchanges even when one party is temporarily offline, through an initial key agreement protocol such as X3DH that uses prekey bundles to enable message sending without immediate key synchronization.[13] This design accommodates out-of-order delivery and lost messages, ensuring resilience in unreliable networks common to mobile applications.[12] Furthermore, it incorporates objectives for detecting message reordering, deletion, or replay attacks by advancing cryptographic states in a way that invalidates outdated or tampered inputs, thereby maintaining the integrity of the conversation chain.[2]
Balancing robust security with practical usability, the algorithm targets efficiency on resource-constrained devices such as smartphones, minimizing computational overhead while providing per-message key uniqueness to prevent mass decryption from single compromises.[2] Introduced in 2016 as part of the Signal Protocol, these objectives address the limitations of prior systems by combining symmetric and asymmetric cryptography to scale for high-volume, privacy-focused communications.[12]
Basic Components
The Double Ratchet Algorithm relies on several fundamental building blocks to achieve its security goals in asynchronous messaging protocols. At its core are three interconnected key derivation function (KDF) chains: the root chain, which manages the overall session state and is updated via Diffie-Hellman exchanges; the sending chain, which derives keys for outgoing messages; and the receiving chain, which handles decryption keys for incoming messages.[2] These chains use a one-way KDF, such as HKDF with HMAC-SHA-256, to generate subsequent keys irreversibly.[2]
Complementing this is the symmetric-key ratchet, which advances the sending and receiving chains sequentially with each message, producing unique message keys for encryption and decryption while enabling secure key deletion for forward secrecy.[2]
The Diffie-Hellman (DH) ratchet is an asymmetric mechanism that employs ephemeral key pairs to periodically refresh the root key through DH exchanges between one party's private ratchet key and the other's public ratchet key.[2] This introduces fresh entropy for post-compromise security and typically uses elliptic curve cryptography, such as Curve25519, for efficient key agreement.[2]
The double ratchet integrates these mechanisms, with the symmetric-key ratchet handling efficient per-message advancements and the DH ratchet intervening to rekey the chains upon receiving a new public key, supporting asynchronous updates and overall security.[2]
The algorithm is initialized with a shared secret from an asynchronous key agreement protocol, such as X3DH, which uses a prekey system of signed prekeys and optional one-time prekeys to allow one party to initiate a session offline.[13]
Technical Functioning
Initialization and Key Agreement
The initialization phase of the Double Ratchet Algorithm occurs prior to message exchange and relies on the Post-Quantum Extended Diffie-Hellman (PQXDH) key agreement protocol within the broader Signal Protocol to establish an initial shared secret between two parties, Alice and Bob.[14] PQXDH enables asynchronous setup by allowing Alice to initiate the key agreement without requiring Bob to be online at that moment. Bob publishes his public keys—a long-term identity key (IK_B), a signed prekey (SPK_B), and optionally one or more one-time prekeys (OPK_B), along with a signed last-resort post-quantum key encapsulation mechanism (PQKEM) prekey (PQSPK_B) and optionally one-time PQKEM prekeys (PQOPK_B)—to a central server, which stores them for retrieval by Alice.[14] Alice fetches Bob's prekey bundle from the server, generates her own ephemeral key pair (EK_A), and verifies the signature on SPK_B using IK_B (and similarly for PQSPK_B) to ensure authenticity.[14]
The core of PQXDH involves computing a shared secret through a combination of classical Diffie-Hellman (DH) exchanges and a post-quantum key encapsulation, typically three or four classical DH plus one PQKEM encapsulation depending on the availability of OPK_B and PQOPK_B. In the basic three-DH case, the shared secret SK is derived as SK = KDF(DH(IK_A, SPK_B) || DH(EK_A, IK_B) || DH(EK_A, SPK_B) || PQ_shared_secret), where PQ_shared_secret is obtained via PQKEM-ENC with Bob's PQ prekey (PQSPK_B or PQOPK_B), and KDF is a key derivation function such as HKDF.[14] If an OPK_B or PQOPK_B is used, additional DH or PQKEM exchanges are incorporated, enhancing forward secrecy by including short-lived keys that are deleted after use.[14] This SK serves as the input for initializing the Double Ratchet state, providing the foundation for subsequent ratcheting while the identity keys offer mutual authentication.[14]
Once SK is established, the Double Ratchet initializes by deriving the root key (RK) and initial chain keys using the HMAC-based key derivation function (HKDF).[1] For Alice (the initiator), the process begins with generating a new DH key pair for the sending ratchet (DHs) and setting the receiving ratchet public key (DHr) to Bob's provided public key. The root key and sending chain key (CKs) are then computed as (RK, CKs) = HKDF_RK(SK || DH(DHs, DHr)), where HKDF_RK is a variant of HKDF that extracts two 32-byte outputs: one for RK and one for CKs.[1] The receiving chain key (CKr) is initially set to null, along with counters for sent messages (Ns = 0), received messages (Nr = 0), previous chain length (PN = 0), and an empty message key skip list (MKSKIPPED = {}).[1]
Bob's initialization mirrors this but starts from SK directly, as he responds to Alice's initial message containing her DH public key. Bob sets his sending ratchet to the DH key pair he used in PQXDH (DHs), initializes RK = SK, and leaves both chain keys (CKs and CKr) as null initially, with the same counter values as Alice.[1] This establishes symmetric sending and receiving chains: the sending chain for deriving message keys in one direction and the receiving chain for the opposite. The following pseudocode outlines the initial state setup for Alice:
RatchetInitAlice(SK, Bob's DH public key):
Generate DH key pair DHs
Set DHr = Bob's DH public key
shared_secret = DH(DHs.private, DHr)
(RK, CKs) = HKDF_RK(SK || shared_secret)
CKr = null
Ns = 0
Nr = 0
PN = 0
MKSKIPPED = {}
RatchetInitAlice(SK, Bob's DH public key):
Generate DH key pair DHs
Set DHr = Bob's DH public key
shared_secret = DH(DHs.private, DHr)
(RK, CKs) = HKDF_RK(SK || shared_secret)
CKr = null
Ns = 0
Nr = 0
PN = 0
MKSKIPPED = {}
For Bob, upon receiving Alice's initial message with her DH public key:
RatchetInitBob(SK, Alice's DH public key):
DHs = Bob's existing DH key pair from PQXDH
DHr = Alice's DH public key
RK = [SK](/page/SK)
CKs = null
CKr = null
Ns = 0
Nr = 0
PN = 0
MKSKIPPED = {}
RatchetInitBob(SK, Alice's DH public key):
DHs = Bob's existing DH key pair from PQXDH
DHr = Alice's DH public key
RK = [SK](/page/SK)
CKs = null
CKr = null
Ns = 0
Nr = 0
PN = 0
MKSKIPPED = {}
These steps ensure the ratchet begins in a synchronized state, ready for the DH ratchet to advance upon the first message exchange.[1]
Ratcheting Mechanisms
The Double Ratchet Algorithm employs two primary ratcheting mechanisms to iteratively advance cryptographic keys, ensuring forward secrecy and post-compromise security during message exchanges. The symmetric-key ratchet operates on a sending or receiving chain to derive unique message keys for each communication, while the Diffie-Hellman (DH) ratchet periodically updates the root key and chain keys using ephemeral key pairs, discarding prior material to limit exposure from compromises. These mechanisms interleave to form a double chain structure, where symmetric ratcheting handles sequential messages and DH ratcheting introduces fresh entropy at intervals.[2]
The symmetric-key ratchet advances a chain key (CK) to produce a message key (MK) for encryption or decryption, using a key derivation function (KDF) based on HMAC-SHA-256. Specifically, the derivation computes the next chain key and message key as follows:
(\text{CK}_{\text{next}}, \text{MK}) = \text{KDF}_{\text{CK}}(\text{CK})
where \text{KDF}_{\text{CK}}(\text{CK}) applies HMAC-SHA-256 with the current CK as the key, iterating over fixed-length constants (0x01 for the message key branch and 0x02 for the next chain key branch) to output 32-byte values for both. This process ensures each message uses a distinct MK, which is deleted after use to minimize storage of sensitive material, and advances the chain unidirectionally to prevent key reuse. The symmetric ratchet maintains separate sending (CKs) and receiving (CKr) chains, incremented on each send or receive operation.[2]
The DH ratchet enhances security by incorporating Diffie-Hellman exchanges to refresh keys, typically triggered when a party receives a message with a new public key. It begins with the generation of a fresh ephemeral DH key pair (DHs) by the sender. The shared DH output is then computed as DH(DHs, DHr), where DHr is the receiver's stored public key. This output updates the root key (RK) and initializes a new receiving chain key (CKr) via:
(\text{RK}_{\text{new}}, \text{CKr}) = \text{KDF}_{\text{RK}}(\text{RK}, \text{DH output})
A symmetric update follows for the sending chain: (\text{RK}_{\text{new}}, \text{CKs}) = \text{KDF}_{\text{RK}}(\text{RK}, \text{DH}(\text{new DHs}, \text{DHr})), where \text{KDF}_{\text{RK}} uses HKDF with SHA-256, taking the old RK as salt and the DH output as input key material (info application-specific). The old DHr is replaced by the new public key, and prior chain keys are discarded, providing forward secrecy by rendering past messages undecryptable even if long-term keys are compromised. DH ratchets occur asynchronously, with the receiver advancing upon detecting a new key in the message header.[2]
To handle out-of-order message delivery, the algorithm supports skipping ahead in the receiving chain up to a limit (MAX_SKIP, typically 1000) to derive message keys for delayed packets without reordering requirements. Upon receiving a message with number Nr and prior chain length PN, if Nr exceeds the current receiving number (state.Nr), the system iterates KDF_CK on CKr until reaching Nr, storing intermediate MKs in a skipped keys dictionary (MKSKIPPED) indexed by the DH ratchet identifier and message number. Pseudocode for this skipping is:
def SkipMessageKeys(state, until):
if state.Nr + MAX_SKIP < until:
raise [Error](/page/Error)() // Skip limit exceeded
if state.CKr is not None:
while state.Nr < until:
state.CKr, mk = KDF_CK(state.CKr)
state.MKSKIPPED[(state.DHr, state.Nr)] = mk
state.Nr += 1
def SkipMessageKeys(state, until):
if state.Nr + MAX_SKIP < until:
raise [Error](/page/Error)() // Skip limit exceeded
if state.CKr is not None:
while state.Nr < until:
state.CKr, mk = KDF_CK(state.CKr)
state.MKSKIPPED[(state.DHr, state.Nr)] = mk
state.Nr += 1
This mechanism accommodates network delays while bounding computational cost and storage.[2]
DH ratchet messages include an encrypted header to convey the new public key and chain metadata securely. Header encryption uses AES-256 in CBC mode for confidentiality, combined with HMAC-SHA-256 for authentication. A header key (HK) and next header key (NHK) are derived via \text{KDF}_{\text{RK-HE}}(\text{RK}, \text{DH output}), producing an 80-byte output: 32 bytes for the AES encryption key, 32 bytes for the HMAC authentication key, and 16 bytes for the initialization vector (IV). The plaintext header (public key, message number Ns, and prior chain length PS) is encrypted as enc_header = AES-CBC-Encrypt(encryption_key, IV, header), with HMAC computed over associated data and the ciphertext for integrity verification. Upon successful decryption, the receiver rotates HK to the precomputed NHK.[2]
The ratchet advancement steps integrate these mechanisms during send and receive operations. On sending (RatchetEncrypt), the symmetric sending chain advances: CKs, MK = KDF_CK(CKs); Ns increments; the message body is encrypted with MK, and the header (if DH ratchet) is prepared accordingly. On receiving (RatchetDecrypt), if a new DH public key is present, DHRatchet is invoked to update DHr, RK, CKs, and CKr; otherwise, SkipMessageKeys handles any gap to Nr, deriving MK = KDF_CK(CKr) for the current message, followed by decryption and incrementing Nr. These steps ensure keys evolve progressively, with DH ratchets resetting chains for security amplification.[2]
Message Processing
In the Double Ratchet Algorithm, message encryption begins by deriving a message key from the current sending chain key using a key derivation function, specifically HKDF with HMAC-SHA-256, which also advances the chain key to produce a new one for the next message.[1] The 32-byte message key is expanded via HKDF-SHA-256 into an 80-byte value (32-byte AES-256 key, 32-byte HMAC-SHA-256 key, 16-byte IV). The plaintext payload is then encrypted using AES-256 in CBC mode with PKCS#7 padding using the derived key and IV, and an authentication tag is computed using the derived HMAC key, truncated to 128 bits (16 bytes) to ensure integrity.[1] This process is encapsulated in the RatchetEncrypt procedure, which advances the symmetric-key ratchet for each outgoing message to generate unique keys, thereby providing forward secrecy for subsequent communications.[1]
When sending a message, the symmetric ratchet is advanced by applying the key derivation function to the current chain key, optionally triggering a Diffie-Hellman ratchet if the receiving chain has been exhausted or if a new ratchet key pair is generated to refresh the session.[1] The resulting ciphertext is paired with a header that includes the sender's current Diffie-Hellman public key (if a DH ratchet step is performed), the previous chain length (PN) indicating the position of the prior chain, and the current message number (N) denoting the position within the current chain.[1] This header, encoded as associated data, is prepended to the ciphertext and authenticated alongside the payload.
On the receiving end, the RatchetDecrypt procedure first inspects the header to determine the appropriate chain for decryption; if the message aligns with the current receiving chain, it derives the message key from the chain key using the same key derivation function, decrypts the payload with AES-256-CBC, and verifies the HMAC-SHA-256 tag.[1] Upon successful decryption and authentication, the receiving chain key is advanced via the symmetric ratchet step.[1] If decryption fails—due to an outdated chain or out-of-order delivery—the algorithm attempts to skip ahead in the chain by deriving and storing skipped message keys (up to a limit of MAX_SKIP, typically 1000) in a dictionary indexed by the sender's public key and message number, or it performs a DH ratchet if a new public key is present in the header.[1]
To handle desynchronization, such as when too many messages are skipped or chains diverge significantly, the receiving party stores provisional skipped keys for potential future decryption; if the skip limit is exceeded or persistent failures occur, the ratchet is reset through a new Diffie-Hellman exchange initiated in a subsequent message, reestablishing synchronized chains.[1] This mechanism, which leverages the ratchet advancement processes detailed elsewhere, ensures that messages can be processed even in asynchronous environments with delayed or reordered deliveries.[1]
Security Properties
Forward Secrecy and Post-Compromise Security
The Double Ratchet Algorithm provides forward secrecy (FS), ensuring that past messages remain secure even if an adversary compromises a party's long-term keys or current session state at a later time. This property is achieved through the use of ephemeral key pairs in the Diffie-Hellman (DH) ratchet and the symmetric-key ratchet, where new message keys are derived for each transmission using a key derivation function (KDF) that prevents backward computation. Specifically, old chain keys are deleted after use, making it computationally infeasible to recover prior message keys from subsequently derived ones, as the ratcheting process introduces fresh entropy via one-way functions.[1]
In addition to FS, the algorithm ensures post-compromise security (PCS), which allows security to be restored for future messages following a temporary compromise of a party's state, such as exposure of private ratchet keys. This is facilitated by the DH ratchet mechanism, where receiving a message with a new public key triggers the generation of fresh root and chain keys from an uncompromised ephemeral private key, effectively evicting the attacker's knowledge and rekeying the session to a clean state. The symmetric-key ratchet complements this by advancing chain keys forward in a one-way manner, limiting the attacker's ability to persist beyond the current chain.[1]
A key aspect of PCS in the Double Ratchet is its self-healing property, where security recovers automatically after a compromise without requiring explicit intervention, provided the adversary does not actively interfere. If multiple messages are missed due to the compromise, the next successful DH ratchet step—triggered by an incoming message with a new ephemeral public key—overwrites the compromised state with new, unpredictable keys derived from added entropy. This healing occurs after the next DH ratchet step, assuming passive adversary behavior post-exposure.[1]
Despite these strengths, the Double Ratchet has limitations in extreme compromise scenarios; furthermore, if chain keys are stolen without a concurrent DH ratchet, an attacker can decrypt messages until the next DH step occurs, highlighting the protocol's reliance on periodic asymmetric advances for full recovery.[15]
Compared to a single symmetric-key ratchet, which offers only forward secrecy by advancing keys in one direction but fails to recover from compromises affecting future messages, the Double Ratchet provides stronger PCS through its combination of symmetric and DH ratchets. This dual approach enables bidirectional key evolution and resilience to state exposure, allowing the protocol to "heal" and maintain security for ongoing communications.[1]
Authentication and Integrity
The Double Ratchet Algorithm provides implicit authentication of messages through keys derived from ratchet chains, which are securely tied to Diffie-Hellman (DH) exchanges between the communicating parties. During initialization and subsequent ratcheting steps, each party generates ephemeral DH key pairs, and the shared secrets computed from these exchanges are input into key derivation functions (KDFs) to produce chain keys. These chain keys then yield unique message keys for each transmission, ensuring that only the legitimate recipient—who possesses the corresponding private keys and can recompute the shared secrets—can derive the correct message key and decrypt the content. This mechanism authenticates the sender implicitly, as an adversary lacking the private keys cannot forge valid message keys without solving the DH problem.[1][16]
Explicit integrity protection is achieved using authenticated encryption schemes, specifically AES-128 in CBC mode combined with HMAC-SHA256 message authentication codes (MACs) applied to the ciphertext and associated data such as the message number. The sender computes the MAC over the encrypted message and includes it in the message structure; upon receipt, the recipient verifies the MAC using the derived message key before decryption. If the MAC fails verification, decryption is aborted, preventing the acceptance of modified or tampered messages. This construction ensures resistance to alterations during transmission, with the HMAC providing collision resistance under the second preimage property of SHA-256. Additionally, the protocol's design avoids long-term signatures on individual messages, enabling plausible deniability: a party can deny authorship of a message since anyone with temporary access to the session keys could generate a valid transcript indistinguishable from one produced by the claimed sender.[1][16]
Replay attacks are thwarted through the use of message counters embedded in headers and the one-way nature of the ratcheting process. Each message includes a sequential message number (N) and the length of the previous chain (PN), allowing the recipient to track the expected order and detect duplicates or out-of-sequence deliveries. Skipped message keys are temporarily stored up to a limit (MAX_SKIP) to handle minor desynchronizations, but the ratchet's forward progression—advancing chain keys irreversibly via KDFs—prevents key reuse even if counters are manipulated. The server's role is limited to relaying opaque messages between endpoints without access to any cryptographic keys, thereby preserving end-to-end integrity and ensuring that intermediaries cannot inspect, modify, or forge content.[1][16]
Early Security Models
The initial formal security analysis of the Double Ratchet Algorithm appeared in the 2016 specification document, with informal discussions of forward secrecy (FS) and post-compromise security (PCS). These discussions relied on the irreversibility of the ratcheting operations, asserting that the one-way nature of the key derivation functions and Diffie-Hellman exchanges prevents an adversary from recovering prior session keys even after compromising long-term secrets or current states. Specifically, the symmetric-key ratchet ensures that advancing the chain discards previous keys, while the Diffie-Hellman ratchet introduces fresh entropy that cannot be reversed, thereby limiting compromise to future messages only.[1]
In 2017, Cohn-Gordon, Cremers, and colleagues conducted the first symbolic security analysis of the Signal protocol, including its Double Ratchet component, using the ProVerif tool to model it as a multi-stage key exchange in an asynchronous setting. Their model proved FS under the assumption of honest Diffie-Hellman oracles, demonstrating that past messages remain secure against adversaries controlling the network and compromising endpoints at any time. However, the analysis highlighted gaps in modeling asynchronous environments, where message reordering or delays could affect forward security due to stored message keys if an adversary exploits skipped ratchet steps before a compromise. The work emphasized session uniqueness by modeling each ratchet advancement as generating distinct, unlinkable keys, but noted that the symbolic abstraction simplified assumptions about message delivery, potentially overlooking real-world desynchronization.[17]
Building on these foundations, Dodis et al. in 2019 introduced modular computational security notions tailored to the Double Ratchet, defining it within a multi-stage adversary framework that captures continuous key evolution. They proved security under the Decisional Diffie-Hellman (DDH) assumption, establishing key independence where each message key is indistinguishable from random and independent of prior or future keys, even against adaptive corruptions. This model formalized session uniqueness by treating ratchet chains as ephemeral sessions, ensuring that compromised states do not link across chains due to fresh Diffie-Hellman inputs. Nonetheless, early proofs, including theirs, inadequately addressed message gaps—scenarios where skipped messages lead to desynchronized ratchets—potentially weakening PCS if gaps allow adversaries to inject or withhold messages before recovery.[18]
Recent Provable Security Results
In recent years, formal analyses of the Double Ratchet (DR) algorithm have advanced toward more comprehensive security proofs, particularly in the universally composable (UC) framework. A key contribution is the development of the functionality F_DR, which captures the DR's achievement of forward secrecy (FS) and post-compromise security (PCS) against adaptive adversaries in a multi-session setting. This UC definition addresses limitations in prior models by incorporating session identifiers, message ordering, and out-of-order delivery, enabling a modular proof that the DR realizes F_DR assuming the underlying continuous key agreement (CKA) and forward-secure authenticated encryption with associated data (FS-AEAD) primitives are secure. The proof demonstrates that the DR protocol securely handles concurrent sessions and adversary corruption of long-term keys, providing a stronger foundation for composable security in end-to-end encrypted messaging systems.[19]
Building on this, analyses have focused on session handling and specific attack models. In a 2023 study using the Tamarin prover, researchers formally verified the DR's security in the presence of session management layers, identifying potential PCS violations due to session reactivation and skipped messages in asynchronous communication, and proving soundness of fixes against clone attacks. The model accounts for skipped messages and asynchronous communication, showing that the DR maintains authentication and confidentiality even under adaptive corruptions with proper isolation, though it highlights potential PCS violations if sessions are not properly isolated. This work extends earlier game-based proofs by automating verification for realistic protocol implementations, confirming soundness against a broad class of adversaries.[20]
Tight security bounds have also been established in the CKA security model. A 2024 proof demonstrates that the DR's multi-session security reduces tightly to the security of its CKA and FS-AEAD components under one-way security assumptions, with the adversary's advantage bounded by O(q \log q), where q is the number of queries. This bound improves upon looser prior reductions by accounting for key-checking attacks and providing concrete security estimates suitable for practical parameter choices. The analysis assumes standard primitives like Diffie-Hellman and AES-GCM, ensuring the DR's efficiency does not compromise provable guarantees.[21]
Logic-based verification has complemented these efforts by targeting specific threats. A 2025 event logic analysis verifies the DR against replay and man-in-the-middle (MITM) attacks using the Logic of Events (LoET) framework, modeling message flows as events to detect inconsistencies in key derivations and authentications. The verification confirms that the ratcheting mechanisms prevent unauthorized message injection or decryption, even with desynchronized chains. These classical proofs establish robust security.[22]
Applications and Implementations
In Messaging Protocols
The Double Ratchet Algorithm forms the foundation of the Signal Protocol, which has provided end-to-end encryption for private one-on-one chats and group calls in the Signal messaging application since its initial deployment in 2013.[1] Developed by Open Whisper Systems, the algorithm enables secure key derivation and message encryption between parties, ensuring that only the communicating devices can access conversation content.
WhatsApp adopted the Signal Protocol, incorporating the Double Ratchet Algorithm, in 2016 to enable end-to-end encryption for all chats, including one-to-one conversations and group messaging through mechanisms like sender keys that leverage ratcheting principles; more recently, in compliance with the European Union's Digital Markets Act, WhatsApp began rolling out interoperability features in November 2025, enabling end-to-end encrypted messaging with select third-party applications such as BirdyChat and Haiket.[23][24] This rollout secured communications for over a billion users by default, applying the algorithm to text, voice, and media exchanges.
Facebook Messenger integrated the Double Ratchet via the Signal Protocol in its Secret Conversations feature launched in 2016, allowing users to opt into end-to-end encrypted private messaging with features like self-destructing messages.[25] The implementation ensures that encrypted sessions remain secure even across devices, with keys managed solely by the endpoints.[26]
Other applications have similarly incorporated the Double Ratchet for robust encryption: Viber enabled it by default in version 6.0 released in 2016 for one-on-one and group interactions; Google Messages began using it for RCS chats in 2021, providing default end-to-end encryption on Android; and Wire employs a variant called Proteus, based on the Double Ratchet, for secure team and personal communications since its 2015 launch.[27][28]
The algorithm also supports federated environments, such as the Matrix protocol, where bridges adapt the Double Ratchet from Signal integrations to enable secure, decentralized cross-network messaging without compromising encryption.[29] This flexibility allows the Double Ratchet to facilitate interoperability in open ecosystems while maintaining its core security guarantees. The adoption across these platforms stems from the algorithm's proven forward secrecy and post-compromise security properties.[1]
The Double Ratchet Algorithm has achieved widespread adoption in end-to-end encrypted messaging systems, serving billions of users globally through major applications. WhatsApp, which integrates the Signal Protocol incorporating the Double Ratchet, reported over 3 billion monthly active users as of March 2025.[30] Signal, the protocol's originator, maintains approximately 70 million monthly active users in 2025.[31] Open-source libraries implementing the algorithm, such as libsignal, are available in languages including Java and Rust, enabling developers to integrate it into diverse platforms and applications.[32]
The algorithm demonstrates efficient performance in real-world deployments, with symmetric ratcheting operations imposing minimal computational overhead suitable for resource-constrained mobile devices. Diffie-Hellman ratcheting, however, introduces higher latency during periodic rekeying due to the cost of elliptic curve computations, potentially impacting user experience in high-volume messaging scenarios.[1]
Key management in Double Ratchet-based systems presents practical challenges, as prekeys must be stored on central servers to facilitate asynchronous messaging, exposing metadata about user relationships and communication patterns to potential leaks or surveillance. Frequent ratcheting for security also contributes to battery drain on mobile devices through repeated cryptographic derivations, necessitating optimizations in implementations.
For interoperability, the Double Ratchet has informed the design of the Messaging Layer Security (MLS) protocol (RFC 9420, 2023) that extends ratcheting mechanisms to support secure group messaging across different services.[33]
Regarding vulnerabilities, the core Double Ratchet Algorithm has withstood extensive cryptanalysis without major breaks. Implementations remain at risk of side-channel attacks, including timing vulnerabilities in the HKDF key derivation function, which require constant-time coding practices to mitigate.[34]
Post-Quantum Extensions
Introduction to SPQR
The Sparse Post-Quantum Ratchet (SPQR) was announced by Signal on October 2, 2025, as a novel extension to the Signal Protocol aimed at providing quantum-resistant security enhancements.[35] This third ratchet layer builds upon the existing Double Ratchet framework by incorporating post-quantum cryptography to address vulnerabilities posed by quantum computing threats, such as the potential for adversaries to harvest encrypted data today and decrypt it later using advanced quantum algorithms.[36]
SPQR employs CRYSTALS-Kyber, standardized as ML-KEM by NIST, for post-quantum key encapsulation mechanisms (KEMs).[35] This integration forms a hybrid-secure system where ML-KEM handles the quantum-safe key exchanges within the ratchet, ensuring that session keys remain protected even against quantum adversaries capable of breaking classical elliptic curve cryptography. The design features a chunked ratchet structure, which divides large key material into smaller chunks using erasure codes (e.g., the 1184-byte encapsulation key into 37 chunks and the 1088-byte ciphertext into 34 chunks, requiring any 10 for reconstruction) to facilitate efficient transmission and reconstruction.[36] Complementing this, sparse advancements optimize bandwidth by incrementally sending key components—starting with minimal initial data (e.g., 64 bytes) followed by parallel bulk transfers—thereby minimizing the overhead of frequent quantum key generation, which can be computationally intensive.[35]
The primary goals of SPQR are to deliver quantum-safe forward secrecy (FS) and post-compromise security (PCS), protecting message chains from both future quantum decryption of past sessions and recovery from device compromises.[36] By ratcheting infrequently to balance robust security and practical performance, SPQR reduces communication costs while maintaining hybrid security guarantees against harvest-now-decrypt-later attacks.[35] This approach ensures that the protocol remains efficient for real-world messaging applications without sacrificing the core ratcheting principles of the original Double Ratchet in the quantum era.[36]
Integration and Benefits
The integration of the Sparse Post-Quantum Ratchet (SPQR) into the Double Ratchet Algorithm forms a Triple Ratchet structure, which combines the original symmetric-key ratchet, the Diffie-Hellman (DH) ratchet, and the new SPQR component. Outputs from these three ratchets are mixed using the HKDF key derivation function to produce hybrid encryption keys, ensuring that the resulting security inherits the strengths of both classical and post-quantum mechanisms.[35] This hybrid approach maintains the forward secrecy (FS) and post-compromise security (PCS) properties of the Double Ratchet while adding quantum resistance.
SPQR integrates by running in parallel with the Double Ratchet to form a Triple Ratchet structure, where the outputs from the symmetric-key ratchet, DH ratchet, and SPQR are mixed using HKDF. It employs ML-KEM for post-quantum key encapsulation in addition to the elliptic curve Diffie-Hellman exchanges. During ratchet steps, the sender encapsulates a shared secret using the recipient's ML-KEM public key, which is included in message headers, and the recipient decapsulates to derive the corresponding key material. This process occurs sparsely—only on select messages—to balance security and efficiency, with the encapsulated ciphertext and associated data enabling continuous quantum-secure key agreement.[35][37]
The primary benefits of this integration include provable quantum-resistant FS and PCS, grounded in the IND-CCA2 security of ML-KEM, which protects against chosen-ciphertext attacks even in the presence of quantum adversaries. Additionally, the design ensures backward compatibility with the classical Double Ratchet mode through a downgrade mechanism, allowing legacy clients to interoperate without immediate upgrades. This hybrid setup provides a gradual transition to post-quantum security without disrupting existing deployments.[35]
SPQR was rolled out in the Signal messaging app by late 2025, enhancing end-to-end encryption for millions of users against potential quantum threats. A production-ready Rust implementation is available on GitHub, facilitating adoption in other protocols.[35][38]
One notable drawback is the increased size of message headers due to ML-KEM public keys and ciphertexts, approximately 1 KB each for ML-KEM-768 parameters (1184 bytes for encapsulation keys and 1088 bytes for ciphertexts). This overhead is mitigated by SPQR's sparse ratcheting, which limits full updates to infrequent intervals, and techniques like chunking and erasure codes to reduce bandwidth impact during transmission.[35]