This question concerns the Signal protocol's X3DH key agreement protocol as documented here.

Obviously, if Alice and Bob have never contacted each other before, they need to run X3DH at least once to agree on a key.

However, it is unclear to me why X3DH needs to be run more than once between the same two users: now that they have agreed on a key, and given the Double Ratchet algorithm is used to generate new keys for each message to ensure perfect forward secrecy, why would they ever need to run X3DH again?

Without the need to run a key agreement protocol a second time between the same two users, a simple DH between Alice and Bob's identity keys should suffice, and perfect forward secrecy is not an issue since the protocol would never be run again. Only if the protocol needs to be run more than once would X3DH be called for, to restore perfect forward secrecy.

I imagine this is due to an implementation decision of not committing any keys beyond the bare minimum (private keys for the identity key, signed prekey and one-time prekeys) to non-volatile storage, so that when the app is restarted, the protocol would need to be run again. Can anyone confirm?

  • 1
    $\begingroup$ Signal has an option for chats called "restart secure session". I'm pretty sure this is what would trigger 3DH to run again. The threat model here would be a leak of the ratchet key, but no leak of the long term identity key. $\endgroup$
    – Natanael
    Feb 17 '19 at 14:41
  • $\begingroup$ @Natanael would you happen to know if, unless this option is triggered, X3DH is never run again? $\endgroup$
    – swineone
    Feb 17 '19 at 14:43
  • $\begingroup$ Not certain. I do believe Signal retains the ratchet key until any of the asymmetric keys involved are replaced (reinstall, etc). A change of long term identity key always trigger a new key exchange. In typical scenarios, the long term identity key and the ratchet key can be assumed to have approximately equal threat models and protection (stored in the same app database). $\endgroup$
    – Natanael
    Feb 17 '19 at 14:47

it is unclear to me why X3DH needs to be run more than once

They don't. X3DH is only used to initialise the session between Alice amd Bob. Once Root key is derived, X3DH is no longer required until one of them reinstalls the app or changes device.

Together with Diffie Hellman ratchet, using KDF

  • Root key derives Chain key and Root key is updated.
  • Chain key derives Message key and Chain key is updated.

Message key is the one which encrypts the message. For every subsequent message, Chain key is updated to derive new Message key.

The process looks something like this:

Double Ratchet

A1 and B1 are Message keys.

Even though the session is not reinitialised periodically, Signal documentation actually recommends this but currently it is not used in practice by either WhatsApp or Signalapp.

4.2. Session expiration It may be desirable for devices to periodically replace old sessions with new sessions, for security purposes.

However, long-term keys of the prekey bundle are still rotated but are not reinitialised with the current recipients.

// Time before rotation of signed prekeys (measured in seconds)
// Currently we rotate signed prekeys every 2 days (48 hours).
// We generate 100 one-time prekeys at a time.  We should
// whenever ~2/3 of them have been consumed.


Identity key is kept same unless the app is reinstalled or the device is changed.

As @Natanael, Signal has an option to restart secure session which reintialises X3DH. There is also a multi-device support in Signal which reintialises X3DH between the recepient and the device. It only happens once with each new device until the app is reinstalled.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.