Following up on my previous mail, I've spent some time thinking more about how 
encrypted mailing lists could be integrated with the current Mailman 
architecture. Based on my current understanding of Mailman Core, Postorius and 
HyperKitty, I tried to sketch a possible message processing pipeline 
architecture diagram here: 
https://www.tldraw.com/f/v4LLMD7t72DyEcbE-J7Qf?d=v-2032.-109.3919.2270.page

The main idea is to allow encrypted delivery in mailing lists, while making 
sure plaintext messages are never stored on disk, but still keeping the 
archives working.

Key management,
- every subscriber provides a PGP public key to Postorius
- Postorius stores subscriber public keys and Mailman core can fetch them 
through the existing API. The mailing list itself also has a keypair (list_pub, 
list_priv) used for receiving encrypted messages
- HyperKitty has an archive keypair (archive_pub, archive_priv) used for 
archive access by subscribers

Sender,
When a sender posts to the mailing list, the sender does two things: encrypt 
the message using list_pub, and optionally sign the message using their private 
key (sender_priv). Mailman Core then receives the encrypted SMTP message.

Mailman Core processes the message roughly as follows:
- decrypt the message using the list private key (list_priv)
- optionally verify the sender signature using the sender’s public key
- generate a random symmetric key K (e.g. AES or ChaCha20)
- encrypt the message body using K
- encrypt K for each subscriber using their public key
- encrypt K once more using the archive public key (archive_pub)
This follows the standard envelope encryption approach: the message itself is 
encrypted once using a symmetric key (K), and that symmetric key is then shared 
with recipients using asymmetric encryption.

Subscriber delivery,
For each subscriber, Mailman sends a message containing:
  - the encrypted message ciphertext  - encrypted_K_user
Each subscriber receives the ciphertext and a copy of the encrypted symmetric 
key K. The subscriber first decrypts encrypted_K_user using their private key 
to recover K, and then uses K to decrypt the message ciphertext.

Archive storage,
For archives, Mailman Core sends HyperKitty two things:
  - the encrypted message ciphertext
  - encrypted_K_archive
HyperKitty stores only encrypted data. When a subscriber requests an archived 
message, HyperKitty decrypts encrypted_K_archive using archive_priv, retrieves 
K, and then decrypts the message so it can be rendered in HTML.

Design tradeoffs,
This design intentionally uses an archive key to support access to historical 
archives. This allows new subscribers to view past messages without needing 
expensive re-encryption of archived content.
The tradeoff is that HyperKitty must hold archive_priv, which means the archive 
server technically can decrypt stored messages. So the system assumes that the 
archive service is trusted to some extent.
However, plaintext messages are never stored on disk, archived data remains 
encrypted at rest, and messages stay encrypted in transit and outside 
controlled processing stages.

Feedback is welcome if I misunderstood any part of the Mailman pipeline or 
component responsibilities.
_______________________________________________
Mailman-Developers mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/mailman-developers.python.org/
Mailman FAQ: https://wiki.list.org/x/AgA3

Security Policy: https://wiki.list.org/x/QIA9

Reply via email to