Discourse Encrypt is a plugin that enables private, encrypted messaging between end-users. All sensitive information is stored securely on the server and is encrypted and decrypted only on the client-side.
Three easy steps to use this plugin:
- enable encryption (generate new private key) and activate it (on current device)
- send an encrypted message (to a user who also enabled encryption)
- read decrypted messages
Note: user was prompted for password again because encryption was deactivated (by logging out or explicitly deactivating it from preferences screen).
How do I install it?
Follow Install a Plugin, using
git clone https://github.com/discourse/discourse-encrypt.git as the plugin command.
Basically, edit your
app.yml file to include the command specified before.
This plugin gives users the possibility to communicate securely through Discourse, by using an end-to-end encryption scheme. Most of the plugin’s logic is implemented on the client side and the server side handles only public or encrypted information. It does not encrypt uploads or metadata (such as names of participants in the conversation, posted time, number of likes, version numbers, etc).
The whole code is open-source and you are welcome to audit it.
This plugin offers integrity and confidentiality of the data (title and text contents of the messages) in certain conditions when the users, servers or the communication channel has been compromised. The goals of this system are to protect the encrypted content against information leaks and unauthorised users. The following sections detail the inner workings of the plugin, threat models and known vulnerabilities of the system.
Figure: Encryption scheme for new topic
Figure: Inviting users to existing topic
This encryption systems uses a set of primitives built on top of those provided by the browser via Web Cryptography API.
Types of keys:
topic keys (AES-256-GCM)
- encrypt all posts (posts are individually encrypted) of a topic
- are generated per topic, on the client-side by the original poster using WebCrypto’s API
- are encrypted with user’s public key for every user that has access to the specific topic using WebCrypto’s API
- are stored (encrypted) on the server side for each user in
RSA keypair (public and private keys) (4096-bits)
- encrypts all topic keys a user has access to
- are generated per user on the client-side by the original poster using WebCrypto’s API
generateKeyprimitive and shared amongst all of user’s devices
- server-side: public key is stored as-is, but private key is stored after encrypting with the private key
client-side: public and private keys are stored as
CryptoKey (extractable: false)in IndexedDb
passphrase keys (derived using PKBDF2 with 128,000 iterations and a 15+ characters passphrase)
Figure: Keys Usage
Most common threat when user gets compromised by having his password stolen or by having other connected accounts (emails or SSO) compromised. In the cases when the attacker does not steal the passphrase too, the data will remain private.
For example, an attacker who hacked user’s email account, would not have access to private communications, but an attacker who installs a key-logger on user’s computer could also steal the passphrase and decrypt messages too.
The second most common type of attack when the server gets compromised and the attacker has full access over the database and web server. Since all the information stored on the server is either encrypted (post contents, conversation keys, private key) or public anyway (public key of the RSA pair), none of the encrypted user data can be decrypted by the attacker.
A rare type of attack where the attacker sits between the user and the server and can read and alter every communication between the two. Because discourse-encrypt messages are encrypted before they leave user’s browser, an attacker cannot read them by simply listening in on the communication.
The attacker would have to actually send a modified version of the website that will secretly decrypt and send back the decrypted messages to the attacker. This is a more difficult and targeted attack that will be executed by a more powerful attacker.
The good part is that there are several ways to protect against this attack and a Discourse installation generally uses HTTPS which greatly reduces the risk of MITM attacks. Another protection mechanism is CSP which helps detecting and mitigating Cross Site Scripting (XSS) attacks and data injection attacks.
In this situation, the attacker gains access to the server hosting Discourse. Such an attacker could change the source code and inject a malicious snipped of code to send back unencrypted data. This is a difficult attack and the attacker must have almost full access to the hosting server (a full leak of the database will not work).
Can I try this out anywhere?
Yes, we set up a test site for Discourse encrypt at: https://try-encrypt.discourse.org/t/how-to-try-out-discourse-encrypt/11 it uses SSO with meta so all you need is a meta account.
Feel free to try it out there.