Project history
Since I started programming, a chat application was kind of a milestone. A very primitive chat application can be developed by making a TCP connection and send a message through it when you press the send button on the form. Not hard at all, but since it involves networking, it's considered stepping to the next level, if you're a complete beginner.
I started tasting C# in the beginning of 2007. Writing a chat application was one of my goals, but due to the lack of knowledge at that time, that wasn't doable. In January 26th, 2008, I finally went for it for the first time.
RS Chat v1
The application made two TCP connections, a server and a client on both ends. I don't know why I did this, since TCP sockets are bidirectional. Probably I didn't know this then.
I really wanted to make it secure, so I made some encryption functions. It used AES and TripleDES, but because I was lacking *real* cryptographic knowledge, they were improperly padded and used ECB. The password was generated dynamically, where I relied on security through obscurity. Yeah, I know now, that's not a good idea, especially when the generated assembly can be really easily decompiled and analysed.
Overall, the application is functional, but has lots of issues.
RS Chat v2
On October 19th, 2009, after gaining some usable knowledge, I restarted the project from scratch. And this time, it only used one TCP socket to communicate. :)
This time I made an actual protocol and documented it. It didn't blindly send strings anymore. It had 7 commands: CONNREQ, CONNOK, PING, PONG, TYPING, NOTTYPING, MESSAGE. Every command ended with a null, so they could be separated on the stream.
For encryption it used Blowfish and AES with a key derived using PBKDF2 which was salted using a shared secret key using Diffie-Hellman key exchange on the CONNREQ command. Optionally it could pass the whole stream through SslStream providing an extra layer of security.
This version had some more advanced features: it could measure connection latency and show when the remote user is typing.
I attempted developing a file transfer feature, but since I was trying to push the file through the active connection, it was extremely slow and blocked the whole connection while the transfer was running.
RS Chat v3
Exactly a year and a day later, on October 20th, 2010, I restarted the development, again, from scratch. This time I'm focusing on performance, extensibility and to do cryptography right.
Now I fully understand the concept of object-oriented programming and I know a thing or two about cryptography.
Main components
When a message is sent or an event is fired, these are the interfaces it needs to goes through – but not in the listed order. Every single part in the application is extensible:
- Connection
This interface makes the connection between the two clients and is responsible for delivering and receivingbyte[]packets. Everything can be used what implements the members of theIConnectioninterface.- TCP sockets
The messages sent on TCP sockets are padded with a 7-bit encoded unsigned 32-bit integer. There's support for SOCKS5 proxies, so you can use an SSH tunnel or an anonymizing service, such as TOR or I2P. - UDP sockets
Full support for connection-less datagrams. Because the application sends pings it'll know when the connection is not alive anymore. - SCTP sockets
An *exotic* transport layer which has the best features of both TCP and UDP. There is no native support in Windows for this protocol, but a port of the BSD SCTP stack to Windows exists: SctpDrv.
- TCP sockets
- Encryption
This interface is responsible for encrypting thebyte[]packets before they are sent. Anything implementing theIEncryptioninterface.- .Net Wrapper
This wrapper provides support for classes which extend theSymmetricAlgorithmclass. This means every encryption algorithm in theSystem.Security.CryptographyandMono.Security.Cryptographynamespace, plus dozens downloadable from the internet. - BouncyCastle Wrapper
This wrapper provides support for every block cipher and stream cipher in the BouncyCastle Extended library. - Multi-Layer Encryption
This isn't an actual encryption provider, since it allows you to create a chain of encryption algorithms therefore allows you to use multiple layers of encryption. No limit is set on the layer count, however there's really no reason to use 5 or more at once... Dedicated to the über-paranoid. :)
- .Net Wrapper
- Key exchange
This is responsible for exchanging keys securely on a connection, therefore even if the passwords were compromised, the connection is still secure due to the randomly generated shared secret key. Anything implementing theIKeyExchangeinterface can be used.- Diffie-Hellman key exchange
Generates 1536-bit keys using the 1536-bit prime number described in RFC 3526. - Elliptic-Curve Diffie-Hellman key exchange
Generates 256-bit keys using the Cryptography API: Next Generation shipped with Windows 7.
- Diffie-Hellman key exchange
- Compression
This is responsible for compressing larger chunks of data. Anything implementing theICompressioninterface can be used. Unfortunately this isn't very useful, since the average size of a packet is about 20 bytes, which can't be compressed.- Deflate
- GZip
- Packet serialization
This interface is responsible for serializing classes intobyte[]and then deserializing them back to their original type on the other end. Anything implementing theISerializerinterface can be used.- Packet Serializer
This is a special class for serializing thePacketand its derived classes into the smallest possible binary form. - Binary Serializer
Packet serialization theBinaryFormatterway. - XML
- BSON
- JSON
- Packet Serializer
- Text formatters
These are used to format your messages.- Markdown
- Textile
File transfers
For the first time ever, I've succeded at implementing high-speed secure file transfers. When a file transfer is initiated, the software creates an unidirectional TCP socket on the server side and starts sending the file. The reason why not necessarily the file sender is used as a server is really simple: it might not be reachable, it might be behind a firewall or NAT. If the client originally used a proxy to create a connection, then that proxy will be contacted again to initiate the file transfer through it.
The file transfer being on another form, thread and connection, has the ability to continue the transfer even if the main chat connection is closed or lost. The connection used for the transfer, as stated above, is unidirectional and will close automatically after the size of the file is received, therefore it's not a security concern.
The speed of the transfers average on 95 MB/s. If encryption is enabled, the speed is really determined by the algorithm in use, but if a high-speed stream cipher is chosen, then the speed is around 60 MB/s.
Identity verification
If you're very paranoid you might be concerned about your connection being rerouted to someone else, or the DNS resolving to the fake IP, or to man-in-the-middle attacks. Version 1 and 2 didn't address this issue. Version 3 however, supports using SSL certificates to authenticate the connection and to tamper-proof every single packet. Any certificate that can be used for email encryption, can be used for this purpose too. You can get fully free email certificates from CACert, StartCom or InstantSSL.
Some ideas
These didn't make it into the software yet, but they're on my TODO list:
- Avatars – Small JPEG pictures could be sent in the handshake
- Smiles and other text formatting features
- Manual confirmation for SSL certificates
- Easier connect window – possibly with a nice wizard-ish design, because the current is far too advanced for a regular user