How to build a highly secure End to End Encryption React Native messaging app - node.js

I just posted this question on security stackexchange and they advised me to move my question to stackoverflow so here it is.
I am currently working on an instant React Native messaging app and I want to implement E2EE (End to End Encryption between the sender and the receiver) for better security. The libraries/frameworks I use are NodeJS for the backend, Socket.io for real-time communication, MongoDB for data management and obviously React Native for the frontend.
At this point, I am able to send messages back and forth from sender to the server and back to the receiver but the server can actually read the messages which is quite anoying because I want to save the messages (encrypted) in my database and retrieve them for the user to see his history.
Recently I found that the Diffie-Hellman key-exchange was a good solution to generate a shared secret key on each endpoint device but I don't know how to implement it in my app.
I also found that big messaging app (like WhatsApp, Facebook Messenger, Signal,... ) uses the Signal Protocol which is based on a X3DH (Extended Triple Diffie-Hellman) and I was wondering if it is possible to implement such a good thing in my RN app. But the problem is that even after reading the Signal Protocol's documentation I could not figure out how to implement it.
In conclusion my question is how can I implement the Signal Protocol in my RN app and uses Socket.io to send and receive encrypted messages? And if for some reason this is not possible, how can I implement the Diffie-Hellman key-exchange algorithm?
Thanks to anyone who can help me!

Related

What is the best way to implement real-time notifications in a MEAN application?

I want to make an app which lets users comment and send messages. However, the notifications for these events will have to come instantly, just like any other social-media or chat application. This is what I'm thinking of:
Web-frontend: Angular, mobile: Ioinc with Angular
Backend: Node, Mongo
Now, this is how I was thinking I'd implement real-time notification.
There's a constant socket connection between the frontend (web & mobile-app) and the backend.
Whenever a message arrives, targeted to a specific user, I'll use some kind of a Mongo-hook to send the notification to the frontend via the socket connection.
Now, the confusion with this approach is:
Would millions of socket connections work at scale, at all? If not, what is the way to implement this pub-sub kind of system? I need to do it from scratch, not using Firebase.
What if a user is offline when he receives the message in the backend? If the socket is not on, how would he get the message? Is there a way to do it using Kafka? Please explain if you have some ideas on this.
Is this the correct approach? If not, can you suggest what would be appropriate?
Would millions of socket connections work at scale, at all? If not, what is the way to implement this pub-sub kind of system? I need to do it from scratch, not using Firebase.
Yes, it can work at scale just you have to made an architecture like that. You might find this useful
Scalable architecture for socket.io
https://socket.io/docs/v3/using-multiple-nodes/
What if a user is offline when he receives the message in the backend? If the socket is not on, how would he get the message?
If he the socket is not on or user is offline, then client Socket will be disconnected. At this point, notification will not be received and whenever the user comes online you'll have make an API call to get the notifications and connect again to the socket for further operations.
Is there a way to do it using Kafka?
Yes, you can also do it with Kafka. You'll need Consumer API(Subscriber) and Producer API(Publisher)
https://kafka.apache.org/documentation/#api
https://www.npmjs.com/package/kafka-node
Sending Apache Kafka data on web page
What do you use Apache Kafka for?
Real time notification with Kafka and NodeJS

How to secure messaging system like RabbitMQ/MQTT for use in a mobile application?

Let's say I want to write a mobile chat application (just as an example).
How to receive only the messages meant for one client and don't let other clients receive messages which where not meant for them!?
Create a temp queue only known to the client? - Secure enough?
Encrypting the message with clients public key? - Own PKI needed!
Restrict access to queues based on some credentials the client sends with every request? - Every request needs to be authenticated!
...?
If a client sends a message to the outgoing queue, how to prevent other clients from reading the message directly out of the queue!?
Restricting access to write-only? - Don't know if this is possible...
Encrypting the message? - Own PKI needed!
...?
I hope my question/problem is clear and I'm really looking forward to hear your ideas and best practices!
Thanks in advance!
//edit: So using a temp queue for every client with encrypted messages might be a good choice. Or do you have any other ideas???
If you use RabbitMQ AMQP broker, then you can use Validated User-ID extension power, but you have to create separate users for each client.
Using per-client queue maybe a good choice, but you have to realize that it "security through obscurity" and it smells. But as you suggested, message encryption may fix that.
You can play with Access Control but you may find better to have some server application to handle complex user management things and use it api from clients for better user policies management.

Efficient Chat Streams

I'm attempting to create an application which will work as a chat app. I'm currently contemplating the best way to do this and I'm thinking of going with a server sent event package such as the following. Every conversation would have an id, and the message would be emitted under the id. For instance
stream.emit(1512, "Hello") would send the message and
stream.on(1512, function(message){console.log(message)}) would print the message. Only the chat members would have the chatId.
I was initially thinking of using websockets but I thought that not every user should be receiving data, as chats were private and I didn't want to configure authentication within websockets.
Back to server sent events:
I have a few questions on the topic.
Are they efficient and, if not, what would be a more efficient solution
Is the method of sending chat through a randomized, hashed, id (such as 309ECC489C12D6EB4CC40F50C902F2B4D) secure?
Would you recommend a different method for sending chat? This is to be implemented as a mobile application where individual users can chat privately with oneanother so, again, security is pretty important.
Thanks.
I recommend the client-call package (disclaimer: I wrote it). It provides a very simple method to run a client-side method from the server code.
Besides this, you can always just put the chat messages to a db collection and remove them after some time.

protocol comparison for notification server with node.js

I'd like to implement push notification server using node.js. The basic scenario is:
Some applications sends notification messages to the server.
Notification server receives the request and forwards the message to uesr's mail or IM client based on user's preference.
In step 1, which protocol (e.g. REST, socket, HTTP/XML and so on.) would you recommend from the performance perspective?
Also in step 2, I have a plan to use node-xmpp module for IM client but for mail, which way is the best to implement? For example,
Just use SMTP. (But I think this might occur performance degradation because SMTP is an expensive communication and performance depends on SMTP server capacity.
use queue mechanism, in order to avoid drawbacks from the above. node.js app simply puts the message into the queue, and smtp server pulls the message.
other solutions...
Thanks in advance.
With regards to what to use as a protocol, i would go for a REST interface, whereby the application posting sends a POST request to a resource associated with the USER. something along the lines of "http://example.com/rest/v1/{userID}/notifications
I personally would use json as the data/content of the rest request and have node.js write this information to a message queue. (as a json string).
You can than have xmpp readers for each user, as well as an SMTP handler reading from this queue as fast as the SMTP server allows it to go.
However, this full post is what i would do in your situation, rather than a factual response on what is best. I know JMS fairly well and i've been working a lot with rest interfaces lately, therefore this is the way i would do it.

How to model Push Notifications on server

Brief Description:
Well, since many days I've been looking for an answer to this question but there seems to be answers for 'How to create a Push Notification Server' and like questions. I am using node.js and it's quite easy to 'create' a push notification server using sock.js (I've heard socket.io isn't good as compared to sock.js). No problem till here. But what I want is how to model such a server.
Details:
OK, so, let's say I've an application where there's a chat service (just an example this is, actual thing is big as you might have guessed). A person sends a message in a room and all the people in the room get notified. But what I want is a 'stateful' chat - that is, I want to store the messages in a data store. Here's where the trouble comes. Storing the message in the database and later telling everyone that "Hey, there's a message for you". This seems easy when we need the real-time activity for just one part of the app. What to do when the whole app is based on real-time communication? Besides this, I also want to have a RESTful api.
My solution (with which I am not really happy)
What I thought of doing was this: (on the server side of course)
Data Store
||
Data Layer (which talks to data store)
||
------------------
| |
Real-Time Server Restful server
And here, the Real-time server listens to interesting events that the data-layer publishes. Whenever something interesting happens, the server notifies the client. But which client? - This is the problem with my method
Hope you can be of help. :)
UPDATE:
I think I forgot to emphasize an important part of my question. How to implement a pub-sub system? (NOTE: I don't want the actual code, I'll manage that myself; just how to go about doing it is where I need some help). The problem is that I get quite boggled when writing the code - what to do how (my confusion is quite apparent from this question itself). Could please provide some references to read or some advice as to how to begin with this thing?
I am not sure if I understood you correctly; but I will summarize how I read it:
We have a real-time chat server that uses socket connections to publish new messages to all connected clients.
We have a database where we want to keep chat logs.
We have also a restful interface to access the realtime server to get current chats in a lazier manner.
And you want to architect your system this way:
In the above diagram, the components I circled with purple curve wants to be updated like all other clients. Am I right? I don't know what you meant with "Data Layer" but I thought it is a daemon that will be writing to database and also interfacing database for other components.
In this architecture, everything is okay in the direction you meant. I mean DataStore is connected by servers to access data, maybe to query client credentials for authentication, maybe to read user preferences etc.
For your other expectation from these components, I mean to allow these components to be updated like connected clients, why don't you allow them to be clients, too?
Your realtime server is a server for clients; but it is also a client for data layer, or database server, if we prefer a more common naming. So we already know that there is nothing that stops a server from being a client. Then, why can't our database system and restful system also be clients? Connect them to realtime server the same way you connect browsers and other clients. Let them enjoy being one of the people. :)
I hope I did not understand everything completely wrong and this makes sense for the question.

Resources