Skip to content
The Double Ratchet — Why Two?
step 1/5

Reading — step 1 of 5

Read

~1 min readDouble Ratchet

The Double Ratchet — Why Two?

After X3DH, both parties share a root key SK. Now they need a way to:

  • Derive fresh per-message keys.
  • Forget old keys (forward secrecy).
  • Recover security after compromise (future secrecy).
  • Handle out-of-order delivery.

Solution: Double Ratchet = two ratchets:

1. Symmetric ratchet (KDF chain):

  • Per direction (sending and receiving).
  • For each message, derive new chain key via KDF: ck_new = HMAC(ck, "1").
  • Message key = mk = HMAC(ck, "2"). Chain key advances; mk used once and discarded.
  • Provides forward secrecy: knowing ck_n doesn't reveal mk_(n-1).

2. DH ratchet (Diffie-Hellman ratchet):

  • Each party has a current DH keypair.
  • When sending after receiving a new DH from the peer: generate new DH keypair, attach public to next message.
  • Compute new DH shared secret. Mix into root_key.
  • Derives new chain keys for both directions.
  • Provides break-in recovery: even if symmetric chain leaks, the next DH ratchet step refreshes everything.

Visual:

SK -> root_key -> DH ratchet step 1 -> sending_chain1 (mk1, mk2, mk3, ...)
                                       receiving_chain1 (mk1, mk2, ...)

         <- new peer DH pubkey arrives ->

       -> DH ratchet step 2 -> sending_chain2, receiving_chain2 ...

Properties:

  • Forward secrecy: per-message keys deleted after use.
  • Break-in recovery: a captured DH state is overwritten on the next ratchet step.
  • Out-of-order delivery: skipped messages saved; their mks derived in advance, stored briefly until delivery.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…