Enforcing user’s privacy from their decentralized social network node admin isn’t an easy task. I explore two potential solutions, the compromising lightweight “Paranoid Mode” and the full-featured “Third-party client”.
At Friendica, a decentralized social network compatible with Diaspora* and Mastodon, we claim protecting user’s privacy, but it’s only true to a limited extent. If users aren’t self-hosting their single-user node, they have to trust the administrator of the node they signed up on as all their data, especially private, will be stored in plain text in the database. Additionally, they have to trust the admin of the remote nodes of whoever they sent private data to, either posts or messages.
We already encrypt the data that’s being transported between nodes, so can we also encrypt the users’ private data? This is a tricky question for web app first as Friendica, Diaspora, Mastodon or Hubzilla. First, let’s review how asymmetric encryption works.
Alice wants to send a message to Bob. She can’t deliver the message herself so she will have to trust it with Carol who will deliver it to Bob. Alice doesn’t want Carol to be able to know what she’s saying to Bob but she doesn’t have a secure way to convene of a shared password with Bob to symmetrically encrypt her messages to Bob.
Instead, Alice and Bob will generate a pair of cryptographic keys. One will be private (Apriv and Bpriv) and will never be sent to anyone, while the public one (Apub and Bpub) will be freely distributed between them through Carol. When Alice wants to send an encrypted message to Bob, she will encrypt the message with Bpub and sign it with Apriv. When bob receive the message, he will first verify the message comes from Alice using Apub and then decrypt the message using Bpriv. Since Carol possesses neither Apriv nor Bpriv, she cannot decrypt the message and can’t fake a signature either to make a message look like it came from Alice.
This whole scenario is based on the assumption that both Alice and Bob are able to keep their private key away from anyone else. Unfortunately, this assumption can’t be guaranteed on a web app where all of the user’s data (cryptographic keys and messages) is stored in the same place. What are the options to add a layer of protection between user’s private data and the admin of their node?
We’ll explore two different solutions, each with their pros and cons. Let’s start with the “paranoid mode”.
Paranoid mode
I have explained this concept in this GitHub issue for Friendica that I will sum up.
In this mode, we generate a key pair for the user and we password-protect the private key with the user’s current authentication password to store it in the database. We use the user’s public key to encrypt any incoming private data from this node or a remote node. This way, the node admin can’t casually read the private data stored in the database.
To read the data, the user has to unlock their private key by providing their password, usually at sign in, and we keep the plain text private key in memory or session or cookie to decrypt any encrypted data before displaying it. When the user signs out, the memory/session/cookie is destroyed, protecting the private key.
Pros:
- No third-party app/client/tool is necessary to safeguard the private key.
- There’s no change to Friendica browsing.
- Protects private data from read and tamper when user is logged out.
- Relatively easy to implement.
Cons:
- The plain text private key is accessible to prying admins when the user’s session is open.
- Private data can still be deleted.
- If the encrypted private key is deleted, the private data can’t be accessed anymore ever.
- It becomes impossible to reset the password as it would lock out the private key and thus the private data forever.
Another alternative (suggested to me by lostinlight) is the third-party client.
Third-party client
In this scenario, Friendica is accessed through its API, a cryptographic key pair is generated, but only the public key is stored on the user’s node. The private key is stored in the third-party client.
Processing incoming private data would work the same as in the Paranoid mode, with encryption with the public key before storage in the database. The API would serve encrypted data to the third-party client which would then decrypt the data for display to the user.
However, Friendica currently publishes a Twitter-like API which allows for existing social networking apps (like Twidere on Android) to support Friendica. This solution would break existing compatibility and require a whole client to be created from the ground up with this feature in mind. Additionally, browsing Friendica through the web interface would be limited to public data as private data couldn’t be decrypted without the private key.
Pros:
- Protects the user’s private data continuously, there’s no window of opportunity for a prying admin.
- Private key can’t be erased by the node admin.
- Password can be freely reset.
Cons:
- Private data can still be deleted.
- Way, way harder to implement.
- Web access would be limited to public data.
What do you think about either solution? Are you afraid your node admin will read/tamper with your private data?
(Banner is “Bombe detail” by Gary Coakley)