Forward secrecy
Even if an attacker records every encrypted message you send today and later compromises your device, they cannot read your past messages. The keys that encrypted them have already been deleted β permanently.
π‘ One sentence definition
Without forward secrecy
Most encryption systems use a single long-term secret for an entire session or conversation. This is efficient, but catastrophic when a key is eventually stolen β and an attacker who has been recording ciphertext since day one can decrypt the entire conversation history retroactively.
With forward secrecy
Encra generates a unique message key for every single message. Each key is derived from the current chain key, used to encrypt exactly one message, then zeroed from memory. Even if an attacker obtains the current chain key, all past message keys are provably gone β they were never stored.
The recorded-traffic attack
The most realistic threat model for forward secrecy is the harvest-now, decrypt-later attack: a passive adversary records all encrypted traffic today, then waits for an opportunity to steal the keys. This is not hypothetical β intelligence agencies and sophisticated attackers routinely store encrypted traffic for future decryption.
How Encra implements it
The Double Ratchet provides forward secrecy through the symmetric KDF chain. For every message:
- A message key is derived:
MK = BLAKE2b(chain_key, 0x01) - The chain key advances:
CK_next = BLAKE2b(chain_key, 0x02) - The message is encrypted with
MKusing XSalsa20-Poly1305. - MK is zeroed from memory β it is never stored to disk, never logged, never persisted.
// Inside DoubleRatchet.encrypt() β simplified
encrypt(plaintext: string): EncryptedMessage {
// Step the symmetric chain β one-way, cannot be reversed
const [newChainKey, messageKey] = kdfChain(this.sendingChainKey)
this.sendingChainKey = newChainKey // advance
this.sendingN++
// Encrypt with the ephemeral message key
const { ciphertext, nonce } = encrypt(plaintext, messageKey)
// Zero the message key β forward secrecy guaranteed from this point
messageKey.fill(0)
return { header: { publicKey: this.dhSendPair.publicKey, n: this.sendingN - 1, pn: this.pn }, ciphertext, nonce }
}βΉ One-way KDF
CK_n+1 from CK_n, but you cannot reverse it to get CK_n-1. This is what makes the chain one-directional β the ratchet only clicks forward.Break-in recovery
Forward secrecy protects past messages. But what about future messages after a breach? The KDF chain alone cannot help here β if the attacker has the current chain key, they can derive all future message keys in that chain.
The DH ratchet solves this. Every time the conversation changes direction (Alice sends, then Bob replies), both sides generate fresh ephemeral key pairs and inject new DH key material into the root key. The old chain key becomes useless for deriving future messages β even if the attacker had it.
Before breach
Session compromised β attacker has chain key
DH ratchet step
New ephemeral key pair generated and exchanged
After breach
Attacker's stolen chain key is now useless β new chain derived from fresh DH secret
This happens automatically on every direction change in the conversation. No user action needed. No re-handshake. No perceptible delay.
π‘ Why this matters in practice
Guarantees & limits
| Threat | Protection | Notes |
|---|---|---|
| Long-term key theft | β Past messages safe | Message keys already deleted; long-term key only affects key registration. |
| Current chain key stolen | β Past messages safe | Only future messages in that chain are at risk until the next DH step. |
| Full device compromise | β Past messages safe | Current and future messages at risk until ratchet fires again. |
| Recorded traffic + future key theft | β Past messages safe | KDF chain is one-way; past message keys cannot be derived. |
| Real-time device access | β Active session at risk | If attacker can read plaintext from the screen or memory as you type, no protocol helps. |
| Server compromise | β All messages safe | Server stores only public keys and encrypted blobs it cannot read. |
π¨ What forward secrecy cannot protect