Writing software and writing about writing software.
For the remote administration program I'm working on right now, I have to learn about a lot of things: p2p networks and cryptography for communication, X11 and Wayland for interaction with the remote computer and Linux in general.
Last post I rambled about my ideas on how to build Liu's p2p network. Now I want to talk a bit about the crypto I'm going to use to avoid being MITMed.
My first idea was pretty simple. I would create an RSA keypair and keep the private key on the server and hardcode the public one on every client. RSA can only encrypt a bit less than the length of the key, so if my key was 2048 bits I would have a little less than 256 bytes for my packet. I decided that I would better use a 4096 bit key so that I had a bit more space to send data to the server. With the public key the clients have, they could send multiple packets encrypted and only the server would be able to decrypt them with the secret key.
Even though this is possible and sounded ok for small messages, I decided I would need more space to send logs and other files. After reading more about RSA I also discovered it's a pretty bad idea to use raw RSA for encryption because reasons. So I decided to mix RSA (asymmetric encryption) with AES (symmetric encryption). My idea was to use it the following way:
- The client has the public key and the server has the private one.
- The client generates an AES key and ecrypts some data.
- The client encrypts the AES key (192 or 256 bits only) with the public RSA key.
- The client sends the now encrypted AES key to the server.
- The client sends the now encrypted data to the server.
- The server decrypts the AES key with the private RSA key.
- The server now has the AES key, that lets us decrypt the data sent by the user.
This is much better than the first option, because we can now encrypt as much data as we want without worrying about splitting the files. We can also encrypt big files much faster because RSA is pretty slow. This technique is also what we use in Liu's encryption plugin to securely encrypt all files in a given computer. The plugin encrypts the files with AES and then sends the AES key encrypted with RSA to the server, removing then the AES from the client's computer. This way we can remotely defend our data in case of an attack.
Even though the protocol seems good, it still lacks more security. The messages sent from the client to the server are encrypted but the ones the server sends to the client are only signed. When you sign a message, you don't encrypt it. You can verify the message was not tampered with in the middle of your connection but people can read whatever you send to clients. So for the protocol to take care of this I need the client to generate another RSA keypair. This time, the client will keep the private and send the public key to the server. This way, both sides of the connection can encrypt the messages with the other's public key and keep the connection secure.
So we can now add as step zero, the exchange of keys, where the client sends the key to the server and the server saves it with some other info needed to connect with the client like the IP and the port where the client listens for instructions.
I want to end the post by saying all this is a very bad idea, you should never roll your own protocol or your own crypto unless you really know what you are doing (and I do not). If you want to use UDP like me and need secure communication you should use DTLS. It's like SSL or TLS but instead of TCP it uses UDP.