we from https://pod-chat.com just wanted to let you know that we have been working really hard for the last 2 years to lift our messenger to the next level and thats why I would like to introduce our latest version of the POD-CHAT Messenger
We have added cool new features and made it very easy to start chatting with your friends from different providers (solidcommunity, inrupt, solidweb…any) and other networks.
We are currently working a PWA and mobile apps. But that will take more time and development.
I hope you guys and girls are just as exited as we are and we hope you will give POD-CHAT a chance and try it for yourself. We really appreciate any feedback (good & bad). This will help us to make this the best decentralized WhatsApp-Alternative out there.
Big shout out and thanks to the community and especially the folks behind the rdflibjs and solid-authn-browser which we use for authentication.
Hey thanks for working on this, we really need a Solid chat so it’s great to see people working on it :).
Something to keep in mind though, is that with the current Solid architecture chats are not secure and it’s very easy to create fake messages and even edit the entire history :(. For example, I just did this and @Vincent can attest he hasn’t written anything:
How to solve this problem is not straight forward, but the issue is that given that I have access to the chat document, I can edit the history in any way I want (like any of the participants). I suppose one way to solve it would be to sign messages using a private/public key that is stored in my Solid POD (and if it doesn’t exist, your app could create it).
Other than that, another suggestion would be to do better error handling. At the moment, it seems like solidcommunity.net is down, but it took me a while to realize that was the problem because I was trying to log in and nothing happened, not even an error message.
thanks for your reply. We have fixed the fake message problem. All messages get signed and verified. If a message is faked it will be marked as “Not signed by owner”. The private key is only readable by the owner and the public key is stored in the public profile.
Concerning the error handling: we are working on it but have been busy with other stuff so it will take a little more time before it will be optimized. But its on our agenda.
Unfortunately, I’ve tried using the app but it doesn’t work, I’m not sure what’s happening It seems to give a 404 error trying to read /pod-chat.com/rsaPrivKey.ttl.acl and that’s the last network request (nothing in the UI nor console).
We have been talking about a generic way to sign data in Solid, and we started about it talking about chat so maybe you’d be interested to check it out. And given that you’ve already implemented this, maybe you can share with us some challenges you found or if something we’ve been talking about doesn’t make sense :). chat can impersonate any webId · Issue #90 · SolidOS/chat-pane · GitHub
I helped implement pod-chat.com.
I am very happy about feedback and would like to take this opportunity
to thank everyone involved in the implementation of the Solid Ecosystem for their great work. @NoelDeMartin The 404 error is an indication that the access rights for the private key generated by the application cannot be set.
Unfortunately, I can’t name the exact cause because I haven’t been able to reproduce this error yet.
The message signing was implemented very close to the suggestions from chat can impersonate any webId · Issue #90 · SolidOS/chat-pane · GitHub.
With our architecture, we follow the approach that everything a user creates belongs to him and only he has control over this data.
This means that a message that a user writes is saved only in that user’s pod.
All other users just get a notification that a new message is ready to be retrieved from the message originator’s pod.
The application then merges the messages from the different pods from each logged-in user’s perspective to form a chat.
We have already implemented three of the points mentioned from the discussion:
save the chat messages on the message creator pod
I explained above how we did it
list authorized origin in ACL
The application sets the rights (acl-File for the directory where all chat data lives) when creating/changing a chat according to the participants in the chat.
used of messages signatures
The application generates a new RSA key pair if it does not already exist.
It would actually be helpful to extend the specification here in order to be able to store private/public keys in a standardized way.
Each message is signed by the author before it is sent. The message is stored in the author’s pod along with the signature.
The readers of the message use the author’s public key to check whether the signature is from him.
However, this doesn’t seem to be working for you.
I hope I was able to give a rough idea of how pod-chat was implemented and I’m looking forward to continuing the discussion at github.
I just wanted to let you know that we have just implemented a “Personal Invitation-Link” which is a link you can share with your friends (from other messengers) and when they login/register using the invitation-link the invitee´s messenger and the inviters messenger will automatically be linked and can immediately start chatting. You can find your individual invitation-link in the lower right corner of your messenger (s. below)
If you want to try it - here is my invitation-link:
I have some remarks regarding the verification implementation and also general problem regarding verification. As far as I can tell from the following piece of code there are some possible issues, depending on the rest of the application and some RDF details I’m not sure of.
A malicious person simply resends (copies) a valid message with the same values (same maker, id, content and signature) to the same or a different chat. This message will still be valid. A classic example would be:
Alice writes to her bank: (“Alice sends Eve 1000€”, signature)
Eve copies the same message: (“Alice sends Eve 1000€”, signature)
The bank sends 2000€ to Eve now, both signatures are valid
To prevent that you need to make sure that all messages are only considered once and duplicates are rejected. For instance, check if the message id exists twice.
Similar to the replay attack, a malicious person could copy a valid message and in this case forward it to a different recipient. Depending on how the message id is handled this would still be considered valid (I’m not sure if the message id implicitly specifies and validates the recipient, as the target chat is probably contained in the url).
Alice writes to her bank Bank1: (“Alice sends Eve 1000€”, signature)
Eve copies the message to Bank2: (“Alice sends Eve 1000€”, signature)
Both Bank1 and Bank2 will think the message is valid and send Eve in total 2000€
To prevent this, the recipient should be in the verification data (similar to the maker now).
A malicious person could create a profile with the same profile picture and name as Alice, but a different web id. If they now send a message it will look like Alice send a message. Verification still succeeds, as it thinks they are completely different users.
Not sure how to prevent this, I guess only by trusting the people which are invited in the chat. But if you trust them, then why do we need to verify the messages in the first place?
Denial of Service
A malicious person could delay verifySignedMessageContent or make it error, which makes it impossible for other users to see messages or any verification result (depending on the rest of the app implementation). To delay it, simply create a really slow response for the public key on the own server. To make it error, maybe return 403 (not sure if this really errors) or invalid base64 for the signature. Because it uses Promise.all it will wait for all and fail if at least one of the verifications fails.
To prevent it, (1) consider to decouple message loading from verifying messages (so the user can read them even if verification is not finished, with a proper “loading verification” UI), and (2) let each message be verified independent of the results of the others (it should succeed without waiting for others).
Thank you for analyzing the security aspects of this application. I have created a general documentation about the structure of turtle resources and the assignment of rights used pod-chat-client/solid-model.md at main · 0l5en/pod-chat-client · GitHub. From my point of view, the cases of replaying attacks/forwarding attacks cannot occur, since the pod of one of the participants would have to be manipulated for this. With the present architecture there is no public pod in which all messages have to be written/appended, instead everyone writes their messages exclusively in their pod and the application combines several chats (one per participant) into one. If Eve wants to copy a message from Alice, she cannot save this copy in Alice or Bob’s pod. In any case, it seems like a good idea to include the creator and recipient in the verification data and to ensure that a message ID isn’t processed twice.
Impersonation sounds very similar to replay attacs. A malicious person cannot write messages to the participants’ pod. The signature is checked to prevent, for example, Bob writing a message in his pod and choosing another valid participant of the chat as the maker.
Hi Ole, thanks for the quick response and the solid model document.
Sounds good. Maybe consider to also add the date (I didn’t think it through, but if someone makes a replay attack they likely want to change the date too to make it appear like a new message rather than a 2nd old one).
Regarding uniqueness, depending on how you do it this will be hard to check. If your application eg only fetches the last 3 days someone could still make a replay attack by copying a message from last week. As the week-old message won’t be loaded it won’t be noticed as a duplicate, even though it’s a replay attack. You could also prevent this by signing the date and verifying that the loaded messages have the expected dates.
Yes, that’s correct. However, assuming Eve is a malicious participant of the chat, Eve can add the message to her pod and achieve the same result. With turtle files you can also describe data located in other pods, even if you don’t have control over them (which imo is unintuitive, but crucial to consider when aggregating data from different sources). I think if you have no explicit protection against this, you just collect all the messages from the different pods and then interpret the messages regardless of their origin.
Consider following example: Eve copies a message of Alice to Eve’s pod. It looks somewhat like this:
# stored on Eve's pod
# describes a message on Alice's pod
"a message from Alice";
Now Bob tries to fetch Alice’s and Eve’s messages. He will read the turtle files, parse them and store their data in a rdf store. Then Bob will extract all messages. Some of the triples describe a message from Alice, thus Bob will think it is from Alice.
I think I didn’t clearly communicate the issue here, so I’ll try to explain it more detailed.
Consider a group chat with Alice, Bob and Eve. Eve is evil and tries to impersonate Alice. Bob opens the chat, looks at the UI and sees this:
The way Bob knows who sent this message is by looking at the profile picture. If it’s the profile picture of Alice, Bob will think Alice sent it. However, nothing prevents Eve to use the same profile picture as Alice. If Eve writes a message and uses Alice’s profile picture, Bob will think the message comes from Alice. This is what I meant with impersonation.
I guess this is especially troublesome in big groups. And also, if Eve really wants to put in a lot of effort, Eve could make it such that only Bob sees the different profile picture, while Alice would see the normal Eve picture (by writing the server, such that it sends different responses based on who asks for it). This would make it even less likely that someone notices this impersonation.
Thank you again for your analysis. The case with the fake picture seems quite difficult to solve. The notes on the signature parts and Turtle specifics were very helpful. I created some new tasks for future improvements on github.
Hello, we have created a new version. We were able to incorporate the points mentioned. If you notice anything else or have other suggestions for improvement, we would be happy to receive any form of help.
I particularly like that the chat treats both participants as equals - i.e. it stores a message in sender’s pod; and also that it sends ActivityStreams activity to inbox of receiver.
AFAIK the previous chat implementations are asymmetric, i.e. they store messages on one pod only.
Have you looked into interoperability with SolidOS and Liqid chat? Is their data structure and business logic compatible with POD-CHAT? If not (perhaps because of the difference mentioned above), have you had any discussions about the interoperable future of solid chats with the folks of the other projects?
I would expect it to be an invitation, rather than directly message, right? (That’s the behaviour I get if I start chat the other way around.)
After clicking the button (the only clickable item), it navigates to https://pod-chat.com/chat/A-POD where A-POD is A’s Pod address (e.g. A.solidcommunity.net).
A never gets a chance to see the message from B, nor will B appear on the right panel (of chat targets/groups, right?). This is behaviour is consistent in my several attempts, even after the “working” way below.
My first attempt was to make A send meeting to B. That worked until allowing B seeing messages and reply. However, A sees two chat channels, and A never sees any message from B – same problem (screenshot) above, and A sees B has not accepted invitation on both channels, even though B sees a new invitation and accepted it.
However, after clearing up the inbox and chat channels, and let A send invitation to B, it works.
On B, I received the following error when trying to open any chat channel through SolidOS:
You seem to have no bookmark file and not even a profile file.
This sounds like not a good sign. I do not get this on A. Not sure if this is related to the previous behaviour.