Quite Intriguing.

22nd July 2021 – If I remember correctly, I was frenetically reading random XMPP blogs on the internet for it was the livestream day, the day after. Panic, kind of. Right since the brainstorming session in the Enigma discord server, the question, “How does WhatsApp work?” intrigued me. Specifically, I so wanted to create my own version of a basic chat system and explore the intricacies of socket programming. Ahh yes, sockets. I’ve always wanted to understand how to use them and how they work. However, I assumed it’s too long of a shot, especially the chat system part. As luck would have it, as I was preparing for the livestream by going through several XMPP blogs, I stumbled upon a blog named, ‘TCPChatRoom’.

I went through the blog and thought to myself “Oh, it is possible indeed.” However, I was sure I had to pick up socket programming before proceeding further. I did watch several tutorials on socket programming and I was able to grasp the basics of sockets. I had to look up documentation of multithreading in python, which was also interesting and implementing it was more fun. After a day of screwing around with threading, I got started to build the basic client to server to client system which did not take a great deal of time, surprisingly. I used the local IP address to test things out and the terminal to send messages. It worked out : ). I was happy, surprised at how quickly I could make a simple system of that sort.  

Local testing

Picture1.png
Picture1.png

I was fairly excited to invite my friends over to the chat room and flex a bit. To the elation’s demise, I needed a public IP address to host my server script, I realized. I tried several means to reserve an external IP address, such as Google Cloud but the registration process seemed protracted plus I had to prepare for the livestream too. Consequently, I just left the code for the time being and went on to enjoy taking part in the livestream.

A few days passed by as I was mucking around on discord, hopping between Enigma and another server, ‘MEC’. I noticed Srikar, the vice-president of the Enigma club using his own public server to handle his discord bots. Needless to say, I just rammed the “Srikar, can I use your server to host my application for once?” question on him out of the blue and he was like “Yea, cool. Socket programming hmm pretty cool.” And proceeded to actually guide me into uploading the server code to his server. We ran the server code on the server and the client code on both our computers, and it simply worked! We were able to chat with each other from different places on Earth.

There were a few minor display text problems as it was only using the command line interface. Basically, the output text was getting mixed up with the input. Accordingly, I had to implement a basic GUI. Hmm…”basic GUI”. It took me a couple of days to muck around with different GUI libraries and choose one. That was when PYSIMPLEGUI saved my lazybones. The name of the library tells it all, it is simple. And so, I got an acutely ugly looking application running thanks to the library. At least the problem was solved, the output and the input sections were at different places. That was all I needed for the time being.

Picture2.png
Picture2.png

/Spoiler

Here comes the major part of the application. Another day in a random discord VC (voice channel), I was showing the chat room to Epoch and Rounak (Raks), joking around how we have insane privacy and we can talk about anything in here (it’s a joke). Although, Epoch quickly replied to that saying “You do know that its not secure right?”. I was not surprised. The messages were not encrypted at all and anyone on a server those messages pass by can literally just read them. Such a shame. And so, I had started to get the hang of basic encryption. I’ve been told by Srikar to implement basic Caesar encryption first and that its fun implementing it on our own. He was not wrong. I had good fun. It is basically shifting the alphabets to n places right. For instance, the encrypted version of “abcd” is “cdef” if the parameter is 2.

It was obvious that bare Caesar encryption is utterly unsafe as all that that someone has to do to crack it, is reverse Caesar it, trying out every number from 1 to 26 as the parameter. Consequently, I started to dig a bit on safe encryption algorithms such as AEC (Advanced Encryption Standard) and RSA. The major difference between them being the symmetricity. In other words, AEC was symmetric which means there will only be a single key to decrypt and encrypt whereas RSA is asymmetric, meaning that the decryption and the encryption keys are distinct. For what I was trying to do, asymmetric encryption seemed like the proper choice because I could share the encryption keys across the servers, not caring about the protection as the encryption key cannot be used for decryption. However, there was a fly in the ointment, the RSA algorithm is a tad bit slower than AEC and the maximum number of characters/key size ratio is smaller to that of AEC too. In the end, I had to choose RSA for its asymmetricity.

Coming to how I implemented the encryption, I wanted the application to be fully end-to-end encrypted (unlike whatscrap), and that meant the private key (decryption one) cannot be shared across the server, that the person on the server side should not be able to read the messages. I could’ve dealt with this by simply using a single pair of keys per chat room, but I just wanted to make the hacker’s life difficult by generating and using a unique pair of public/private keys for every user in the chat room. Consequently, this made it look a bit complicated because it implied that every single client encrypts the arbitrary message using each and every client’s public key, and each client decrypts every message received using its own unshared private key and show it on the screen if the key combination works. (I just maintained a dynamic public key list across the clients) So, in this case, each client is sending one message ‘n’ times where ‘n’ is the total number of clients connected to the room. This is what came to my mind in the start (it surprisingly worked). As I started to implement it, things did not go simply because the TCP protocol I was using only supports byte-stream and not message-stream, which means that the recv(size) function waits until the messages add up to ‘size’ number of bytes, to receive the information. So, the messages could not be received serially. I thought it was all messed up only until I realized, the length of all the RSA (2048-bit key size) encrypted messages is the same. I was able to keep the ‘size’ static. Not to mention, the Caesar encryption was also there all the time, and the parameter for it is taken from the public key of the client. This makes the parameter unique for every client too. In closing, every message gets Caesar encrypted first and then RSA encrypted.

Here’s how “oh hello there” looks like after being encrypted with basic Caesar algorithm and a 2048-bit RSA key:

Picture3.png
Picture3.png
Picture3.png
Picture3.png