# Autocrypt key rotation

**URL:** <https://support.delta.chat/t/autocrypt-key-rotation/2936>\
**Category:** Feature Proposal\
**Created:** [February 19, 2024, 5:30am UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936 "2024-02-19T05:30:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![link2xt](https://support.delta.chat/user_avatar/support.delta.chat/link2xt/32/1971_2.png) [@link2xt](https://support.delta.chat/u/link2xt)\
**Post date:** [February 19, 2024, 5:30am UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/1 "2024-02-19T05:30:09Z")

</div>

Delta Chat uses Autocrypt for encryption.  
Autocrypt standard specifies that OpenPGP key  
conists of a signing EdDSA identity key  
and encryption ECDH subkey.  
Delta Chat allows to import OpenPGP keys  
that do not conform to Autocrypt specification,  
but let’s assume that primary key is capable of signing.

To rotate encryption key,  
we need to remove all existing subkeys from OpenPGP key,  
then generate and add a new encryption subkey.  
To retain the ability to decrypt messages encrypted to old keys,  
we need to store old encryption keys.  
The simplest way is to clone the whole OpenPGP key  
before rotation and store it in the `keypairs` table.  
We can delete old keys after some time to provide Forward Secrecy.

To make key rotation work we need contacts  
to accept the new Autocrypt key  
as long as the primary key is not changed.  
In many places we already compare primary key fingerprints  
instead of the whole keys,  
but changing the subkey has never been tested.  
Most likely in the current state it will  
not work as expected with “verified” keys  
because they are stored separately from Autocrypt keys  
and will not be updated when a new Autocrypt  
key is received with known primary key  
and updated encryption subkey.  
Implmenting this key update logic  
is the main step to make key rotation work.

Besides that, we need to test how Thunderbird reacts  
to receiving an Autocrypt key with new encryption subkey.

All user devices have the same OpenPGP key,  
so rotatitng the key  
requires distributing new key to all devices.  
The key has to be delivered to other devices  
without using the old encryption key  
to make it secure in case an attacker  
can listen to the channel used for key distribution.

The simplest way would be  
to use Autocrypt Setup Message for this.  
Making key distribution explicit  
prevents attacks where encryption key  
is silently changed by an attacker  
getting access to one of the devices device.

Distributing the key to other email clients  
is also a problem.  
Unfortunately, recent Thunderbird 115  
does not support Autocrypt Setup Message.  
In most cases reading chat messages  
in Thunderbird is only useful for debugging,  
so this problem is likely  
not a concern for most users.

Another more complicated option  
would be to introduce individual device keys.  
Each device generates locally an OpenPGP device key  
and distributes the public key to other devices  
via synchronization messages.  
Device secret keys should not be exported in a backup.  
New devices should be explicitly approved by the user.  
When some device wants to rotate the encryption key,  
it can encrypt new key to all known device keys.  
Devices can rotate their keys as frequently as wanted.

Third option is to use ratcheting,  
i.e. calculating each next encryption key  
by hashing previous encryption key.  
Disadvantage is that this approach does not provide Post Compromise Security.  
If old encryption key is leaked, new keys can be derived from it.  
Ratcheting is only useful if device is configured to delete old messages  
in which case attacker cannot use recent key to decrypt old messages stored on the server.  
Post Compromise Security is useful not only in the case  
when user keeps using previously compromised device,  
but also when attacker gets access to old backup of the user device.

---

<div class="post-metadata">

**Author:** ![link2xt](https://support.delta.chat/user_avatar/support.delta.chat/link2xt/32/1971_2.png) [@link2xt](https://support.delta.chat/u/link2xt)\
**Post date:** [February 26, 2024, 4:04pm UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/2 "2024-02-26T16:04:28Z")

</div>

# Related

Time-based ratcheting for OpenPGP (2021): [Perfect forward secrecy in PGP with time-based ratcheting](https://yanmaani.github.io/perfect-forward-secrecy-in-pgp-with-time-based-ratcheting/)

Previous discussions on forward secrecy with OpenPGP:

> **[moving-forward.pdf](https://sequoia-pgp.org/talks/2018-08-moving-forward/moving-forward.pdf)**
>
> 410.68 KB

There is a Double Ratchet implementation on top of OpenPGP at [sequoia-pgp / openpgp-dr · GitLab](https://gitlab.com/sequoia-pgp/openpgp-dr) with documentation at [openpgp\_dr - Rust](https://sequoia-pgp.gitlab.io/openpgp-dr/openpgp_dr/index.html)

Forum topic on Off-the-Record chats:

> [@Off-the-Record chats](https://support.delta.chat/t/off-the-record-chats/1181):
>
> Delta Chat uses OpenPGP for encryption, which does not support forward secrecy. Apart from backwards compatibility, the greatest obstacle to adding forward secrecy is multidevice support. Double Ratchet protocols (Signal protocol, XMPP OMEMO, Olm, Megolm) do not advance the ratchet on devices which are not participating in the chat, [which could be a problem if one of the devices is offline for a long time](https://blog.jabberhead.tk/2019/12/13/pitfalls-for-omemo-implementations-part-1-inactive-devices/). Since different devices use different keys, the protocol also depends on the server publi…

---

<div class="post-metadata">

**Author:** ![monperrus](https://support.delta.chat/user_avatar/support.delta.chat/monperrus/32/2244_2.png) [@monperrus](https://support.delta.chat/u/monperrus)\
**Post date:** [December 22, 2024, 7:39am UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/3 "2024-12-22T07:39:40Z")

</div>

Loving this proposal @link2xt

For the record, have been collecting pointers on this topic at [Email forward secrecy / double ratchet / off-the-records for autocrypt · Issue #444 · autocrypt/autocrypt · GitHub](https://github.com/autocrypt/autocrypt/issues/444)

---

<div class="post-metadata">

**Author:** ![link2xt](https://support.delta.chat/user_avatar/support.delta.chat/link2xt/32/1971_2.png) [@link2xt](https://support.delta.chat/u/link2xt)\
**Post date:** [April 26, 2025, 3:04am UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/4 "2025-04-26T03:04:39Z")

</div>

> [@link2xt](#):
>
> To rotate encryption key, we need to remove all existing subkeys from OpenPGP key, then generate and add a new encryption subkey.

Removing subkeys is however not compatible with how OpenPGP implementations traditionally treat subkeys. [OpenPGP certificates are treated as append-only](https://openpgp.dev/book/adv/certificates.html#certificates-are-effectively-append-only-data-structures), so some email client receiving all our Autocrypt headers over time can [merge](https://www.ietf.org/archive/id/draft-dkg-openpgp-stateless-cli-13.html#name-merge-certs-merge-openpgp-c) the certificates into a single huge certificate with all subkeys ever seen, both old and new.

Then once a large certificate is merged, it is not defined how subkeys used for encryption are selected. Some implementations will encrypt only to the most recent subkey and therefore can remove all old subkeys, but some implementations encrypt to all subkeys. There is a recent 2025-04-06 discussion on subkey selection at [[openpgp] Encryption subkey selection](https://mailarchive.ietf.org/arch/msg/openpgp/FMzCI78v8fcRyGovPHpv8ZvxVnI/) with the proposal to introduce “rank” for subkeys.

Without introduction of new mechanisms such as key rank, we can use subkeys with expiration. The problem with expiration is that if you have not interacted with some contact for a while and the most recent subkey has expired, we will not be able to encrypt to this contact anymore. This is a common problem with expiration, also with TLS certificates. One solution would be to remember the last set of subkeys we used, and if at some point we cannot get a new set of usable subkeys from the certificate, use the last set we used.

---

<div class="post-metadata">

**Author:** ![hpk](https://support.delta.chat/user_avatar/support.delta.chat/hpk/32/9_2.png) [@hpk](https://support.delta.chat/u/hpk)\
**Post date:** [April 26, 2025, 8:38am UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/5 "2025-04-26T08:38:50Z")

</div>

Key rotation sounds generally more interesting than expiration to me. But even with key rotation,

- without some simulation modeling there is a high risk talking about lots of technicalities without having an informed idea of outcomes.

- there is an inherent dependency on how keys are distributed. If we have assisted flows for requesting updated keys it could be easier to rotate keys.

- without analysis on user experience outcomes key rotation/expiry could become a bug/issue generator for years to come.

---

<div class="post-metadata">

**Author:** ![link2xt](https://support.delta.chat/user_avatar/support.delta.chat/link2xt/32/1971_2.png) [@link2xt](https://support.delta.chat/u/link2xt)\
**Post date:** [May 7, 2025, 4:05pm UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/6 "2025-05-07T16:05:15Z")

</div>

> [@link2xt](#):
>
> The problem with expiration is that if you have not interacted with some contact for a while and the most recent subkey has expired, we will not be able to encrypt to this contact anymore. This is a common problem with expiration, also with TLS certificates. One solution would be to remember the last set of subkeys we used, and if at some point we cannot get a new set of usable subkeys from the certificate, use the last set we used.

Even if we encrypt to the last usable set of subkeys, if the keys were already deleted by the receiver, the receiver will receive undecipherable message.

To avoid “unable to decrypt” errors, we need to either send the message unencrypted or always have a fallback key that does not expire.

If we add a fallback key, there is a problem that encryption subkey selection is not specified:

> **[\[openpgp\] Encryption subkey selection](https://mailarchive.ietf.org/arch/msg/openpgp/FMzCI78v8fcRyGovPHpv8ZvxVnI/)**
>
> Search IETF mail list archives

So some implementations may select the expiring key, but some implementation may always select both the expiring key and the fallback key.

---

<div class="post-metadata">

**Author:** ![r10s](https://support.delta.chat/user_avatar/support.delta.chat/r10s/32/1513_2.png) [@r10s](https://support.delta.chat/u/r10s)\
**Post date:** [October 6, 2026, 3:19pm UTC](https://support.delta.chat/t/autocrypt-key-rotation/2936/7 "2026-10-06T15:19:42Z")

</div>


