Take a look at this technical white paper from WhatsApp, they recently moved to the Signal Protocol for e2e encryption.
Public Key Types
Identity Key Pair – A long-term Curve25519 key pair,
generated at install time.
Signed Pre Key – A medium-term Curve25519 key pair,
generated at install time, signed by the Identity Key, and rotated
on a periodic timed basis.
One-Time Pre Keys – A queue of Curve25519 key pairs for one
time use, generated at install time, and replenished as needed.
Session Key Types
Root Key – A 32-byte value that is used to create Chain Keys.
Chain Key – A 32-byte value that is used to create Message
Keys.
Message Key – An 80-byte value that is used to encrypt message
contents. 32 bytes are used for an AES-256 key, 32 bytes for a
HMAC-SHA256 key, and 16 bytes for an IV.
To establish a session:
- The initiating client (“initiator”) requests the public
Identity Key,
public Signed Pre Key, and a single public One-Time Pre Key
for the recipient.
- The server returns the requested public key values. A
One-Time
Pre Key is only used once, so it is removed from server storage
after being requested. If the recipient’s latest batch of One-Time
Pre Keys has been consumed and the recipient has not replenished
them, no One-Time Pre Key will be returned.
- The initiator saves the recipient’s
Identity Key as Irecipient, the
Signed Pre Key as Srecipient, and the One-Time Pre Key as
Orecipient.
- The initiator generates an ephemeral Curve25519 key pair,
Einitiator.
- The initiator loads its own
Identity Key as Iinitiator.
- The initiator calculates a master secret as
master_secret =
ECDH(Iinitiator, Srecipient) || ECDH(Einitiator, Irecipient) ||
ECDH(Einitiator, Srecipient) || ECDH(Einitiator, Orecipient).
If there is no One Time Pre Key, the final ECDH is omitted.
- The initiator uses HKDF to create a
Root Key and Chain Keys
from the master_secret.
Receiving Session Setup
After building a long-running encryption session, the initiator can immediately
start sending messages to the recipient, even if the recipient is offline.
Until the recipient responds, the initiator includes the information (in the
header of all messages sent) that the recipient requires to build a corresponding
session. This includes the initiator’s Einitiator and Iinitiator.
When the recipient receives a message that includes session setup
information:
- The recipient calculates the corresponding
master_secret using
its own private keys and the public keys advertised in the header of
the incoming message.
- The recipient deletes the
One-Time Pre Key used by the initiator.
- The initiator uses HKDF to derive a corresponding
Root Key and
Chain Keys from the master_secret.