RS Chat
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 sending 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 January 26th, 2008
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.
Screenshot
RS Chat v2 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](http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx)
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.
Screenshots
RS Chat v3 October 20th, 2010
Exactly a year and a day later, 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 receiving
byte[]
packets. Everything can be used what implements the members of the IConnection
interface.
- 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.
- Encryption
This interface is responsible for encrypting the
byte[]
packets before they are sent. Anything implementing the IEncryption
interface.
- .Net Wrapper
This wrapper provides support for classes which extend the
SymmetricAlgorithm
class. This means every encryption algorithm in the System.Security.Cryptography
and Mono.Security.Cryptography
namespace, 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. :)
- 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 the
IKeyExchange
interface 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.
- Compression
This is responsible for compressing larger chunks of data. Anything implementing the
ICompression
interface 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.
- Packet serialization
This interface is responsible for serializing classes into
byte[]
and then deserializing them back to their original type on the other end. Anything implementing the ISerializer
interface can be used.
- Packet Serializer
This is a special class for serializing the
Packet
and its derived classes into the smallest possible binary form.
- Binary Serializer
Packet serialization the
BinaryFormatter
way.
- XML
- BSON
- JSON
- Text formatters
These are used to format your messages.
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
Screenshots
Encrypted file transfers
This transfer has been proxied through a public anonymous proxy so I could capture the file transfer. It's safe to do this, because the connection is encrypted and every packet is signed to prevent tampering.
New connection window
The settings aren't sent in the handshake packet, which means if your settings don't match, the connection will fail instantly.
RS Chat v4 August 18th, 2012
The development has been restarted, however this time it's only developed as a low-priority hobby project, and I mainly focus on writing clean code behind a thought-out and extensible architecture.
The project is currently under development. As of now, there isn't even an UI or a protocol, just a bunch of classes.
Things implemented so far
- Connection
This interface is responsible for delivering
byte[]
packets between two clients.
- TCP sockets
- Data separation
The problem with TCP is that packets are buffered when sent, and reconstructed into a stream at the other side. The separation of messages needs to be done in client code. The following methods are implemented:
- Length-padding of messages using an 8 to 64-bit unsigned integer
- Buffering incoming messages and separating them when a
byte[]
sequence is encountered
- No message separation; fires an event if 1 or more bytes were read into the 8192-byte buffer
- Connection helpers
These classes can override the behaviour of
TCPSocket.Connect()
- SOCKS5
Initiates the TCP connection through a SOCKS5 proxy.
- HTTPS
Initiates the TCP connection through a HTTP proxy that supports the
CONNECT
method to ports other than 443.
- UDP sockets
- Data separation
The problem with UDP is that packets are not guaranteed to be delivered, and they can be up to only 65536 bytes in size. For messages more than 65 kB, the packet will be fragmented. The following methods are implemented for packet reconstruction:
- Length-padding of messages using an 8 to 64-bit unsigned integer
- Buffering incoming messages and separating them when a
byte[]
sequence is encountered
- No message separation; fires an event for each incoming UDP packet
- Protocols
This interface is responsible for actually communicating once a connection is opened.
- Plain-text protocol
This protocol was supposed to be similar syntactically to the IRC protocol. It isn't the default protocol, since it is only implemented for fun, debugging and educational purposes. It's a priority to make the protocol as simple as possible so you are able to telnet into the software and chat, but add complex features to it as well, so when humans are not involved, the software will be able to initiate videochat sessions.
- Binary protocol
This is the smallest, fastest and default protocol. The smallest payload is 2 bytes, which is the unsigned 16-bit identifier of an
Event
object which will be initialized and fired at the other end. Additional bytes will be deserialized into an object array and passed to the Event
.
- Encryption
This interface is responsible for encrypting the
byte[]
packets before they are sent.
- .Net Framework
This provider adds support for classes which extend the
SymmetricAlgorithm
class. This means every encryption algorithm in the System.Security.Cryptography
and Mono.Security.Cryptography
namespace, plus dozens downloadable from the internet.
- BouncyCastle
This provider adds support for every block cipher and stream cipher in the BouncyCastle Extended library.
- Crypto++
This provider adds support for the block and stream ciphers implemented in the Crypto++ library. A native
CryptoPPHelper
VC++ project (CryptoPP.dll and CryptoPP64.dll) exposes the classes from within Crypto++ and the RoliSoft.Chat.Encryption.Providers.CryptoPP
C# project provides the P/Invoke interfaces to communicate with it.
- Botan
This provider adds support for the block and stream ciphers implemented in the Botan library. A native
BotanPPHelper
VC++ project (Botan.dll and Botan64.dll) exposes the classes from within Botan and the RoliSoft.Chat.Encryption.Providers.Botan
C# project provides the P/Invoke interfaces to communicate with it.
- MCrypt
This provider adds support for the block and stream ciphers implemented in the library version of MCrypt. The
RoliSoft.Chat.Encryption.Providers.MCrypt
C# project communicates via P/Invoke with the untouched libmcrypt.dll file compiled in VC++. The x64 compilation of libmcrypt was problematic, therefore it is not available. If an x64 process must use the libmcrypt library, it can do it by spawning a separate x86 process (the RoliSoft.Chat.Helpers.MCryptIPCHost
project) with which it will communicate using IPC named pipes.
- OpenSSL
This provider adds support for the block and stream ciphers implemented in OpenSSL. The
RoliSoft.Chat.Encryption.Providers.OpenSSL
C# project communicates via P/Invoke with the untouched libeay32.dll and ssleay32.dll files compiled in VC++ for both x86 and x64 separately.
- Compression
This interface is responsible for compressing the
byte[]
packets before they are sent.
- .Net Framework
This provider adds support for the Deflate and GZip algorithms implemented in the .Net Framework.
- SharpCompress
This provider adds support for the algorithms implemented in the SharpCompress library. These are managed implementations, and the really good algorithms (such as PPMd for text compression) tend to be a bit slow and introduce a visible lag.
- SevenZipSharp
This provider adds support for the algorithms implemented in the native 7zip library through the managed SevenZipSharp library. These algorithms are unmanaged and run pretty fast, however they're not compatible with Mono.
- Hashing
This interface is responsible for hashing the
byte[]
packets before they are sent.
- .Net Framework
This provider adds support for classes which extend the
HashAlgorithm
class. This means every hashing algorithm in the System.Security.Cryptography
and Mono.Security.Cryptography
namespace, plus dozens downloadable from the internet.
- BouncyCastle
This provider adds support for every hash algorithm in the BouncyCastle Extended library.
- HashLib
This provider adds support for the hash algorithms implemented in the HashLib library.
- Crypto++
This provider adds support for the hash algorithms implemented in the Crypto++ library. A native
CryptoPPHelper
VC++ project (CryptoPP.dll and CryptoPP64.dll) exposes the classes from within Crypto++ and the RoliSoft.Chat.Hashing.Providers.CryptoPP
C# project provides the P/Invoke interfaces to communicate with it.
- Botan
This provider adds support for the hash algorithms implemented in the Botan library. A native
BotanPPHelper
VC++ project (Botan.dll and Botan64.dll) exposes the classes from within Botan and the RoliSoft.Chat.Hashing.Providers.Botan
C# project provides the P/Invoke interfaces to communicate with it.
- MHash
This provider adds support for the hash algorithms implemented in the library version of MHash. The
RoliSoft.Chat.Hashing.Providers.MHash
C# project communicates via P/Invoke with the untouched libmhash.dll file compiled in VC++. The x64 compilation of libmhash was problematic, therefore it is not available. If an x64 process must use the libmhash library, it can do it by spawning a separate x86 process (the RoliSoft.Chat.Helpers.MCryptIPCHost
project) with which it will communicate using IPC named pipes.
- OpenSSL
This provider adds support for the hash algorithms implemented in OpenSSL. The
RoliSoft.Chat.Hashing.Providers.OpenSSL
C# project communicates via P/Invoke with the untouched libeay32.dll and ssleay32.dll files compiled in VC++ for both x86 and x64 separately.
Things to be implemented
- Anonymous communication through deepwebs
The considered protocols are:
- Tor
Both sides would run a Tor client with a hidden service. Packets will be onion-routed between two
.onion
destinations, therefore they'd go completely through Tor and never reach clearnet.
- I2P
Both sides would run an I2P client with a local destination tunnel, or whatever the hell they call it. Packets will be garlic-routed between two
.b32.i2p
destinations, therefore they'd go completely through I2P and never reach clearnet.
- Hyperboria
To reach this network, nothing else may be required other than IPv6 support. Which is already supported. More info coming soon.
- Identity store in public DHTs
An identity, public key, or most likely hash of public key may be stored in a decentralized database, for IP address retrieval by other parties that want to contact the said identity. Since the software doesn't have millions of active users, I was thinking of abusing currently active DHTs:
- Mainline DHT
You are probably connected to it right now: are you running µTorrent or an other DHT-capable BitTorrent client? Then you are.
The software would insert the IP address and hash of your public key as a "torrent infohash" into the DHT.
- Azureus DHT
Same as the last one, except this is a slightly modified one for Vuze users.
- Kademlia
This network is used between eMule users. Can be bootstrapped very easily by fetching a nodes.dat file from nodes-dat.com. The software may also look for an active installation of eMule and use its nodes.dat file.
- User discovery on the same subnet
Each software would listen on a specific UDP port and answer to broadcast UDP packets with its identity. The broadcast UDP packet will contain the identity of the sender, therefore a user on the same subnet may choose to ignore broadcast packets from specific identities, thus appearing offline or non-existent to begin with.
- Communication protocols
The following protocols are yet to be implemented:
- RPC-like via packet serialization
Objects on both sides will be serialized with a CLR object serializer then exchanged and deserialized.
- BinaryFormatter
- Google Protocol Buffers
- Apache Thrift
- Apache Avro
- MessagePack
- JSON
- BSON
- BEncode
- XML
- File transfers
- Voice calls
- Video calls
- Interoperability with other protocols
Only open protocols that allow external connections in their specifications will be supported. No interaction with Yahoo/MSN/Skype, since those protocols are closed and require an account with their operator.
- DCC chat with IRC users by IP
- Chat with Jabber users
- Call and text with SIP/VoIP addresses
Communication protocols
Plain-text protocol
This protocol was supposed to be similar syntactically to the IRC protocol. It isn't the default protocol, since it is only implemented for fun, debugging and educational purposes. A typical chat session looks like this:
HELLO RoliSoft rolisoft@gmail.com | -> HelloEvent, String name, String email
PING 1234567890 | -> PingEvent, Long timestamp
TYPNG 1 | -> TypingEvent, Boolean isOccurring
MSG This is a message. | -> MessageEvent, LeftoverString message
BYE | -> ByeEvent
Binary protocol
This is the smallest, fastest and default protocol. A packet looks like this:
+--------------+[+--------------+]
| EVENT UID |[| ARGUMENTS |]
| 2 bytes |[| |]
| uint16 |[| |]
+--------------+[+--------------+]
Arguments are optional, but since most of the events contain some kind of data (TypingEvent
has bool IsOccurring
, PingEvent
has ulong Timestamp
, etc) the following bytes are deserialized into an object[]
instance, via a pre-mapped event-arguments-datatype list. The datatypes can be one of the following:
- Boolean – 1 byte, 0 => false, 1 => true
- Int – 4 bytes, signed 32-bit integer
- Long – 8 bytes, signed 64-bit integer
- Float – 4 bytes, signed 32-bit floating point integer
- Double – 8 bytes, signed 64-bit floating point integer
- String
- Binary: 7-bit formatted unsigned 24-bit integer length padding + UTF-8 character sequence
- Text: read characters until space (ASCII
0x20
) is encountered unless escaped with \
(ASCII 0x5C
)
- LeftoverString
- Binary: 7-bit formatted unsigned 24-bit integer length padding + UTF-8 character sequence
- Text: decode as string until the end of the packet is reached
- DateTime – 8 bytes, unsigned 64-bit integer representing a binary
DateTime
value
- ByteArray
- Binary: unsigned 32-bit integer length padding + byte array
- Text: Base64-encoded string representation of the byte array
Once the communication protocol deserialized the arguments into an object[]
instance, the LoadArguments(object[])
method will be called on the previously initialized Event
object. Once the event has been successfully reconstructed, whoever is listening on the PacketReceived
event of the communication protocol will receive this object.
Supported algorithms and benchmarks
Compression
Toggle benchmark table of supported compression algorithms.
Provider | Algorithm | Ratio | Compression | Decompression |
.Net Framework | Deflate | 66.44% | 10.28 MB/s | 17.74 MB/s |
.Net Framework | GZip | 66.44% | 9.92 MB/s | 14.35 MB/s |
SharpCompress | Deflate | 66.60% | 6.25 MB/s | 9.86 MB/s |
SharpCompress | Zlib | 66.60% | 6.79 MB/s | 15.87 MB/s |
SharpCompress | GZip | 66.60% | 6.59 MB/s | 13.48 MB/s |
SharpCompress | BZip2 | 75.58% | 3.56 MB/s | 1.90 MB/s |
SharpCompress | LZMA | 73.85% | 0.92 MB/s | 5.92 MB/s |
SharpCompress | PPMd | 78.94% | 2.49 MB/s | 0.60 MB/s |
SevenZipSharp | Deflate | 73.87% | 2.80 MB/s | 5.12 MB/s |
SevenZipSharp | Deflate64 | 73.87% | 3.06 MB/s | 12.43 MB/s |
SevenZipSharp | BZip2 | 75.57% | 0.71 MB/s | 5.15 MB/s |
SevenZipSharp | LZMA | 73.87% | 3.16 MB/s | 12.34 MB/s |
SevenZipSharp | LZMA2 | 73.87% | 3.12 MB/s | 12.50 MB/s |
SevenZipSharp | PPMd | 78.53% | 3.43 MB/s | 0.72 MB/s |
Encryption
Toggle benchmark table of supported encryption algorithms.
Provider | Algorithm | Encryption | Decryption |
.Net Framework | Rijndael | 24.76 MB/s | 21.22 MB/s |
.Net Framework | TripleDES | 21.35 MB/s | 21.42 MB/s |
.Net Framework | RC2 | 35.24 MB/s | 46.20 MB/s |
.Net Framework | DES | 54.38 MB/s | 56.04 MB/s |
BouncyCastle | AES | 22.55 MB/s | 24.05 MB/s |
BouncyCastle | Blowfish | 38.71 MB/s | 37.33 MB/s |
BouncyCastle | Camellia | 23.02 MB/s | 24.81 MB/s |
BouncyCastle | Camellia | 11.75 MB/s | 12.17 MB/s |
BouncyCastle | CAST5 | 23.73 MB/s | 28.68 MB/s |
BouncyCastle | CAST6 | 24.12 MB/s | 24.71 MB/s |
BouncyCastle | DES | 22.95 MB/s | 23.18 MB/s |
BouncyCastle | DESede | 9.07 MB/s | 8.98 MB/s |
BouncyCastle | Gost28147 | 14.56 MB/s | 14.39 MB/s |
BouncyCastle | Noekeon | 13.68 MB/s | 12.79 MB/s |
BouncyCastle | RC2 | 18.04 MB/s | 20.61 MB/s |
BouncyCastle | RC5-32 | 35.63 MB/s | 35.87 MB/s |
BouncyCastle | RC5-64 | 26.32 MB/s | 28.83 MB/s |
BouncyCastle | RC6 | 32.04 MB/s | 32.55 MB/s |
BouncyCastle | SEED | 14.92 MB/s | 15.18 MB/s |
BouncyCastle | Serpent | 12.49 MB/s | 12.14 MB/s |
BouncyCastle | SKIPJACK | 15.43 MB/s | 12.93 MB/s |
BouncyCastle | TEA | 31.84 MB/s | 31.14 MB/s |
BouncyCastle | Twofish | 34.25 MB/s | 36.75 MB/s |
BouncyCastle | XTEA | 30.34 MB/s | 30.03 MB/s |
BouncyCastle | HC-128 | 79.56 MB/s | 96.17 MB/s |
BouncyCastle | HC-256 | 80.32 MB/s | 90.92 MB/s |
BouncyCastle | ISAAC | 44.79 MB/s | 51.87 MB/s |
BouncyCastle | RC4 | 77.75 MB/s | 83.33 MB/s |
BouncyCastle | Salsa20 | 28.83 MB/s | 32.12 MB/s |
BouncyCastle | VMPC | 75.52 MB/s | 82.16 MB/s |
BouncyCastle | VMPC-KSA3 | 77.89 MB/s | 82.62 MB/s |
Crypto++ | AES | 105.00 MB/s | 66.21 MB/s |
Crypto++ | RC6 | 121.19 MB/s | 130.47 MB/s |
Crypto++ | MARS | 74.16 MB/s | 77.71 MB/s |
Crypto++ | Twofish | 93.50 MB/s | 88.12 MB/s |
Crypto++ | Serpent | 49.11 MB/s | 53.31 MB/s |
Crypto++ | CAST-256 | 70.80 MB/s | 74.10 MB/s |
Crypto++ | CAST-128 | 78.03 MB/s | 81.25 MB/s |
Crypto++ | IDEA | 52.42 MB/s | 55.09 MB/s |
Crypto++ | DES | 49.96 MB/s | 52.40 MB/s |
Crypto++ | DES-EDE2 | 21.74 MB/s | 22.33 MB/s |
Crypto++ | DES-EDE3 | 21.85 MB/s | 22.20 MB/s |
Crypto++ | DES-XEX3 | 44.33 MB/s | 46.63 MB/s |
Crypto++ | Camellia | 69.47 MB/s | 71.56 MB/s |
Crypto++ | SEED | 47.38 MB/s | 48.22 MB/s |
Crypto++ | RC5 | 113.99 MB/s | 136.61 MB/s |
Crypto++ | Blowfish | 73.39 MB/s | 78.62 MB/s |
Crypto++ | TEA | 40.30 MB/s | 41.24 MB/s |
Crypto++ | XTEA | 39.51 MB/s | 41.67 MB/s |
Crypto++ | SKIPJACK | 25.35 MB/s | 26.04 MB/s |
Crypto++ | GOST | 47.86 MB/s | 33.80 MB/s |
Crypto++ | RC2 | 29.09 MB/s | 36.56 MB/s |
Crypto++ | SAFER-K | 37.89 MB/s | 50.69 MB/s |
Crypto++ | SAFER-SK | 38.70 MB/s | 48.80 MB/s |
Crypto++ | SHACAL-2 | 76.72 MB/s | 89.16 MB/s |
Crypto++ | SHARK-E | 74.93 MB/s | 81.51 MB/s |
Crypto++ | Square | 114.62 MB/s | 116.79 MB/s |
Crypto++ | 3-Way | 81.31 MB/s | 74.12 MB/s |
Crypto++ | Panama-LE | 338.41 MB/s | 344.93 MB/s |
Crypto++ | Sosemanuk | 333.49 MB/s | 321.25 MB/s |
Crypto++ | Salsa20 | 289.50 MB/s | 279.20 MB/s |
Crypto++ | XSalsa20 | 281.34 MB/s | 272.00 MB/s |
Crypto++ | ARC4 | 220.26 MB/s | 201.43 MB/s |
Crypto++ | MARC4 | 220.88 MB/s | 208.05 MB/s |
Crypto++ | SEAL-3.0-BE | 269.94 MB/s | 259.30 MB/s |
Botan | AES-256 | 79.95 MB/s | 93.81 MB/s |
Botan | AES-192 | 98.45 MB/s | 108.51 MB/s |
Botan | AES-128 | 108.82 MB/s | 120.81 MB/s |
Botan | Blowfish | 64.60 MB/s | 73.89 MB/s |
Botan | Camellia-256 | 32.77 MB/s | 34.12 MB/s |
Botan | Camellia-192 | 32.65 MB/s | 34.06 MB/s |
Botan | Camellia-128 | 39.75 MB/s | 41.29 MB/s |
Botan | CAST-256 | 42.63 MB/s | 44.15 MB/s |
Botan | CAST-128 | 61.98 MB/s | 71.34 MB/s |
Botan | DES | 37.57 MB/s | 41.70 MB/s |
Botan | TripleDES | 16.49 MB/s | 17.28 MB/s |
Botan | DESX | 35.49 MB/s | 30.57 MB/s |
Botan | Noekeon | 53.63 MB/s | 124.11 MB/s |
Botan | RC6 | 101.86 MB/s | 119.46 MB/s |
Botan | SEED | 54.97 MB/s | 56.27 MB/s |
Botan | Serpent | 37.36 MB/s | 62.93 MB/s |
Botan | Skipjack | 13.46 MB/s | 13.88 MB/s |
Botan | TEA | 35.99 MB/s | 39.52 MB/s |
Botan | Twofish | 87.70 MB/s | 92.26 MB/s |
Botan | XTEA | 36.55 MB/s | 158.86 MB/s |
Botan | MISTY1 | 45.92 MB/s | 49.92 MB/s |
Botan | KASUMI | 37.70 MB/s | 39.94 MB/s |
Botan | WiderWake4+1-BE | 312.19 MB/s | 292.35 MB/s |
Botan | Square | 95.59 MB/s | 102.16 MB/s |
Botan | IDEA | 27.28 MB/s | 152.29 MB/s |
Botan | RC2 | 29.16 MB/s | 37.83 MB/s |
Botan | Turing | 218.61 MB/s | 194.70 MB/s |
Botan | MARS | 66.68 MB/s | 67.84 MB/s |
Botan | GOST-28147-89(R3411_94) | 37.75 MB/s | 41.65 MB/s |
Botan | RC5(12) | 89.00 MB/s | 119.67 MB/s |
Botan | SAFER-SK(10) | 30.08 MB/s | 24.22 MB/s |
Botan | ARC4 | 124.39 MB/s | 120.97 MB/s |
Botan | RC4_skip(768) | 115.74 MB/s | 114.92 MB/s |
Provider | Algorithm | Encryption | Decryption |
OpenSSL | AES-128-CBC | 103.91 MB/s | 162.95 MB/s |
OpenSSL | AES-128-CFB | 163.88 MB/s | 152.56 MB/s |
OpenSSL | AES-128-CTR | 172.30 MB/s | 169.38 MB/s |
OpenSSL | AES-128-ECB | 156.14 MB/s | 148.44 MB/s |
OpenSSL | AES-128-OFB | 170.70 MB/s | 156.68 MB/s |
OpenSSL | AES-128-XTS | 156.61 MB/s | 68.78 MB/s |
OpenSSL | AES-192-CBC | 124.65 MB/s | 120.50 MB/s |
OpenSSL | AES-192-CFB | 146.98 MB/s | 148.44 MB/s |
OpenSSL | AES-192-CTR | 152.06 MB/s | 149.21 MB/s |
OpenSSL | AES-192-ECB | 143.54 MB/s | 136.26 MB/s |
OpenSSL | AES-192-OFB | 155.65 MB/s | 141.51 MB/s |
OpenSSL | AES-256-CBC | 81.27 MB/s | 121.94 MB/s |
OpenSSL | AES-256-CFB | 130.90 MB/s | 115.35 MB/s |
OpenSSL | AES-256-CTR | 135.33 MB/s | 136.67 MB/s |
OpenSSL | AES-256-ECB | 133.02 MB/s | 122.24 MB/s |
OpenSSL | AES-256-OFB | 140.85 MB/s | 137.57 MB/s |
OpenSSL | AES-256-XTS | 130.95 MB/s | 111.83 MB/s |
OpenSSL | AES-128-CBC | 82.36 MB/s | 167.92 MB/s |
OpenSSL | AES-192-CBC | 124.96 MB/s | 136.67 MB/s |
OpenSSL | AES-256-CBC | 129.62 MB/s | 129.08 MB/s |
OpenSSL | BF-CBC | 93.48 MB/s | 100.83 MB/s |
OpenSSL | BF-CBC | 92.65 MB/s | 97.78 MB/s |
OpenSSL | BF-CFB | 74.07 MB/s | 76.40 MB/s |
OpenSSL | BF-ECB | 56.50 MB/s | 83.51 MB/s |
OpenSSL | BF-OFB | 83.20 MB/s | 86.31 MB/s |
OpenSSL | CAMELLIA-128-CBC | 109.87 MB/s | 119.90 MB/s |
OpenSSL | CAMELLIA-128-CFB | 111.25 MB/s | 107.67 MB/s |
OpenSSL | CAMELLIA-128-ECB | 104.90 MB/s | 107.47 MB/s |
OpenSSL | CAMELLIA-128-OFB | 109.69 MB/s | 109.31 MB/s |
OpenSSL | CAMELLIA-192-CBC | 89.33 MB/s | 93.20 MB/s |
OpenSSL | CAMELLIA-192-CFB | 84.21 MB/s | 79.85 MB/s |
OpenSSL | CAMELLIA-192-ECB | 78.35 MB/s | 83.23 MB/s |
OpenSSL | CAMELLIA-192-OFB | 81.76 MB/s | 46.47 MB/s |
OpenSSL | CAMELLIA-256-CBC | 69.32 MB/s | 90.69 MB/s |
OpenSSL | CAMELLIA-256-CFB | 87.98 MB/s | 87.28 MB/s |
OpenSSL | CAMELLIA-256-ECB | 85.41 MB/s | 90.68 MB/s |
OpenSSL | CAMELLIA-256-OFB | 90.86 MB/s | 86.47 MB/s |
OpenSSL | CAMELLIA-128-CBC | 109.19 MB/s | 117.12 MB/s |
OpenSSL | CAMELLIA-192-CBC | 89.80 MB/s | 91.41 MB/s |
OpenSSL | CAMELLIA-256-CBC | 88.64 MB/s | 89.75 MB/s |
OpenSSL | CAST5-CBC | 92.10 MB/s | 95.15 MB/s |
OpenSSL | CAST5-CBC | 86.55 MB/s | 87.92 MB/s |
OpenSSL | CAST5-CBC | 47.83 MB/s | 90.40 MB/s |
OpenSSL | CAST5-CFB | 73.75 MB/s | 76.95 MB/s |
OpenSSL | CAST5-ECB | 81.36 MB/s | 83.29 MB/s |
OpenSSL | CAST5-OFB | 83.66 MB/s | 82.63 MB/s |
OpenSSL | DES-CBC | 61.93 MB/s | 64.45 MB/s |
OpenSSL | DES-CBC | 61.96 MB/s | 65.52 MB/s |
OpenSSL | DES-CFB | 53.23 MB/s | 53.50 MB/s |
OpenSSL | DES-ECB | 55.77 MB/s | 57.69 MB/s |
OpenSSL | DES-EDE | 23.32 MB/s | 24.25 MB/s |
OpenSSL | DES-EDE-CBC | 20.09 MB/s | 24.01 MB/s |
OpenSSL | DES-EDE-CFB | 23.16 MB/s | 23.32 MB/s |
OpenSSL | DES-EDE-OFB | 23.63 MB/s | 23.67 MB/s |
OpenSSL | DES-EDE3 | 23.74 MB/s | 24.35 MB/s |
OpenSSL | DES-EDE3-CBC | 24.96 MB/s | 25.51 MB/s |
OpenSSL | DES-EDE3-CFB | 23.49 MB/s | 23.37 MB/s |
OpenSSL | DES-EDE3-OFB | 23.70 MB/s | 23.73 MB/s |
OpenSSL | DES-OFB | 56.27 MB/s | 56.52 MB/s |
OpenSSL | DES-EDE3-CBC | 24.94 MB/s | 25.54 MB/s |
OpenSSL | DESX-CBC | 57.16 MB/s | 37.40 MB/s |
OpenSSL | DESX-CBC | 50.34 MB/s | 59.24 MB/s |
OpenSSL | IDEA-CBC | 50.40 MB/s | 51.58 MB/s |
OpenSSL | IDEA-CBC | 50.33 MB/s | 52.11 MB/s |
OpenSSL | IDEA-CFB | 47.45 MB/s | 47.23 MB/s |
OpenSSL | IDEA-ECB | 48.85 MB/s | 49.58 MB/s |
OpenSSL | IDEA-OFB | 49.95 MB/s | 49.65 MB/s |
OpenSSL | RC2-CBC | 25.04 MB/s | 39.08 MB/s |
OpenSSL | RC2-40-CBC | 25.11 MB/s | 39.28 MB/s |
OpenSSL | RC2-64-CBC | 24.99 MB/s | 39.01 MB/s |
OpenSSL | RC2-CBC | 19.66 MB/s | 38.84 MB/s |
OpenSSL | RC2-CFB | 23.96 MB/s | 24.09 MB/s |
OpenSSL | RC2-ECB | 24.48 MB/s | 37.75 MB/s |
OpenSSL | RC2-OFB | 24.53 MB/s | 24.59 MB/s |
OpenSSL | RC4 | 306.89 MB/s | 284.77 MB/s |
OpenSSL | RC4-40 | 308.32 MB/s | 269.38 MB/s |
OpenSSL | RC4-HMAC-MD5 | 191.79 MB/s | 197.62 MB/s |
OpenSSL | SEED-CBC | 52.99 MB/s | 54.26 MB/s |
OpenSSL | SEED-CBC | 53.07 MB/s | 53.48 MB/s |
OpenSSL | SEED-CFB | 54.01 MB/s | 35.56 MB/s |
OpenSSL | SEED-ECB | 50.62 MB/s | 49.51 MB/s |
OpenSSL | SEED-OFB | 54.43 MB/s | 54.90 MB/s |
MCrypt | cast-128 | 67.77 MB/s | 67.02 MB/s |
MCrypt | gost | 27.74 MB/s | 27.27 MB/s |
MCrypt | rijndael-128 | 32.25 MB/s | 32.00 MB/s |
MCrypt | twofish | 56.75 MB/s | 82.28 MB/s |
MCrypt | arcfour | 231.52 MB/s | 245.37 MB/s |
MCrypt | cast-256 | 53.69 MB/s | 51.58 MB/s |
MCrypt | loki97 | 17.53 MB/s | 17.69 MB/s |
MCrypt | rijndael-192 | 33.46 MB/s | 32.64 MB/s |
MCrypt | saferplus | 7.78 MB/s | 12.08 MB/s |
MCrypt | wake | 150.42 MB/s | 72.42 MB/s |
MCrypt | blowfish-compat | 80.87 MB/s | 71.89 MB/s |
MCrypt | des | 20.98 MB/s | 20.67 MB/s |
MCrypt | rijndael-256 | 33.73 MB/s | 32.23 MB/s |
MCrypt | serpent | 27.98 MB/s | 29.57 MB/s |
MCrypt | xtea | 36.32 MB/s | 34.58 MB/s |
MCrypt | blowfish | 78.79 MB/s | 70.11 MB/s |
MCrypt | enigma | 215.33 MB/s | 212.34 MB/s |
MCrypt | rc2 | 15.32 MB/s | 21.71 MB/s |
MCrypt | tripledes | 11.07 MB/s | 10.74 MB/s |
Hashing
Toggle benchmark table of supported hashing algorithms.
Provider | Algorithm | Speed |
.Net Framework | SHA1 | 377.44 MB/s |
.Net Framework | SHA256 | 69.10 MB/s |
.Net Framework | SHA384 | 14.75 MB/s |
.Net Framework | SHA512 | 14.76 MB/s |
.Net Framework | RIPEMD160 | 68.02 MB/s |
.Net Framework | MD5 | 425.88 MB/s |
BouncyCastle | Gost3411 | 2.02 MB/s |
BouncyCastle | MD2 | 7.95 MB/s |
BouncyCastle | MD4 | 112.58 MB/s |
BouncyCastle | MD5 | 94.25 MB/s |
BouncyCastle | RIPEMD128 | 49.99 MB/s |
BouncyCastle | RIPEMD160 | 34.25 MB/s |
BouncyCastle | RIPEMD256 | 50.98 MB/s |
BouncyCastle | RIPEMD320 | 33.98 MB/s |
BouncyCastle | SHA-1 | 73.11 MB/s |
BouncyCastle | SHA-224 | 47.34 MB/s |
BouncyCastle | SHA-256 | 35.88 MB/s |
BouncyCastle | SHA-384 | 29.42 MB/s |
BouncyCastle | SHA-512 | 32.12 MB/s |
BouncyCastle | Tiger | 47.86 MB/s |
BouncyCastle | Whirlpool | 4.63 MB/s |
Botan | Adler32 | 1072.10 MB/s |
Botan | BMW512 | 115.81 MB/s |
Botan | CRC24 | 360.25 MB/s |
Botan | CRC32 | 484.80 MB/s |
Botan | GOST-R-34.11-94 | 14.31 MB/s |
Botan | HAS-160 | 333.66 MB/s |
Botan | Keccak-1600(512) | 22.97 MB/s |
Botan | MD2 | 5.26 MB/s |
Botan | MD4 | 539.29 MB/s |
Botan | MD5 | 404.71 MB/s |
Botan | RIPEMD-128 | 283.24 MB/s |
Botan | RIPEMD-160 | 192.02 MB/s |
Botan | SHA-160 | 352.11 MB/s |
Botan | SHA-224 | 147.42 MB/s |
Botan | SHA-256 | 147.34 MB/s |
Botan | SHA-384 | 21.71 MB/s |
Botan | SHA-512 | 21.93 MB/s |
Botan | Skein-512(512) | 60.94 MB/s |
Botan | Tiger(24,3) | 115.69 MB/s |
Botan | Whirlpool | 38.94 MB/s |
Crypto++ | SHA-1 | 278.55 MB/s |
Crypto++ | SHA-224 | 187.69 MB/s |
Crypto++ | SHA-256 | 185.72 MB/s |
Crypto++ | SHA-384 | 171.63 MB/s |
Crypto++ | SHA-512 | 173.16 MB/s |
Crypto++ | Tiger | 367.12 MB/s |
Crypto++ | Whirlpool | 102.32 MB/s |
Crypto++ | RIPEMD-160 | 167.18 MB/s |
Crypto++ | RIPEMD-320 | 180.84 MB/s |
Crypto++ | RIPEMD-128 | 235.61 MB/s |
Crypto++ | RIPEMD-256 | 260.79 MB/s |
Crypto++ | MD2 | 5.85 MB/s |
Crypto++ | MD4 | 597.13 MB/s |
Crypto++ | MD5 | 400.39 MB/s |
Crypto++ | CRC32 | 526.82 MB/s |
Crypto++ | Adler32 | 1705.31 MB/s |
MHash | CRC32 | 214.18 MB/s |
MHash | MD5 | 333.05 MB/s |
MHash | SHA1 | 197.96 MB/s |
MHash | HAVAL256 | 168.13 MB/s |
MHash | RIPEMD160 | 133.00 MB/s |
MHash | TIGER | 122.98 MB/s |
MHash | GOST | 29.27 MB/s |
MHash | CRC32B | 252.53 MB/s |
MHash | HAVAL224 | 170.32 MB/s |
MHash | HAVAL192 | 170.84 MB/s |
MHash | HAVAL160 | 169.92 MB/s |
MHash | HAVAL128 | 169.64 MB/s |
MHash | TIGER128 | 123.79 MB/s |
MHash | TIGER160 | 123.91 MB/s |
MHash | MD4 | 514.44 MB/s |
MHash | SHA256 | 96.19 MB/s |
OpenSSL | DSA | 316.76 MB/s |
OpenSSL | DSA-SHA | 509.27 MB/s |
OpenSSL | DSA-SHA1 | 510.75 MB/s |
OpenSSL | DSA-SHA1-old | 509.48 MB/s |
OpenSSL | DSS1 | 511.58 MB/s |
OpenSSL | MD4 | 623.94 MB/s |
OpenSSL | MD5 | 544.55 MB/s |
OpenSSL | MDC2 | 13.44 MB/s |
OpenSSL | RIPEMD160 | 203.50 MB/s |
OpenSSL | RSA-MD4 | 626.76 MB/s |
OpenSSL | RSA-MD5 | 550.54 MB/s |
OpenSSL | RSA-MDC2 | 13.36 MB/s |
OpenSSL | RSA-RIPEMD160 | 203.80 MB/s |
OpenSSL | RSA-SHA | 293.99 MB/s |
OpenSSL | RSA-SHA1 | 510.29 MB/s |
OpenSSL | RSA-SHA1-2 | 502.96 MB/s |
OpenSSL | RSA-SHA224 | 166.59 MB/s |
OpenSSL | RSA-SHA256 | 166.38 MB/s |
OpenSSL | RSA-SHA384 | 156.92 MB/s |
OpenSSL | RSA-SHA512 | 156.18 MB/s |
OpenSSL | SHA | 294.03 MB/s |
OpenSSL | SHA1 | 507.20 MB/s |
OpenSSL | SHA224 | 164.49 MB/s |
OpenSSL | SHA256 | 165.02 MB/s |
OpenSSL | SHA384 | 156.47 MB/s |
OpenSSL | SHA512 | 156.33 MB/s |
OpenSSL | ssl2-md5 | 550.78 MB/s |
OpenSSL | ssl3-md5 | 547.26 MB/s |
OpenSSL | ssl3-sha1 | 508.94 MB/s |
OpenSSL | whirlpool | 31.47 MB/s |
Provider | Algorithm | Speed |
HashLib | Adler32 | 106.73 MB/s |
HashLib | AP | 248.83 MB/s |
HashLib | Bernstein | 306.91 MB/s |
HashLib | Bernstein1 | 312.72 MB/s |
HashLib | BKDR | 310.02 MB/s |
HashLib | Blake224 | 45.56 MB/s |
HashLib | Blake256 | 64.45 MB/s |
HashLib | Blake384 | 20.42 MB/s |
HashLib | Blake512 | 24.56 MB/s |
HashLib | BlueMidnightWish224 | 56.20 MB/s |
HashLib | BlueMidnightWish256 | 141.00 MB/s |
HashLib | BlueMidnightWish384 | 58.81 MB/s |
HashLib | BlueMidnightWish512 | 132.97 MB/s |
HashLib | CRC32a | 223.66 MB/s |
HashLib | CRC32b | 239.21 MB/s |
HashLib | CRC32c | 238.98 MB/s |
HashLib | CRC32d | 238.24 MB/s |
HashLib | CRC64a | 147.97 MB/s |
HashLib | CRC64b | 153.51 MB/s |
HashLib | CubeHash224 | 9.42 MB/s |
HashLib | CubeHash256 | 9.33 MB/s |
HashLib | CubeHash384 | 9.40 MB/s |
HashLib | CubeHash512 | 9.38 MB/s |
HashLib | DEK | 477.94 MB/s |
HashLib | DJB | 306.40 MB/s |
HashLib | DotNet | 202.99 MB/s |
HashLib | Echo224 | 19.41 MB/s |
HashLib | Echo256 | 23.80 MB/s |
HashLib | Echo384 | 11.40 MB/s |
HashLib | Echo512 | 12.74 MB/s |
HashLib | ELF | 125.35 MB/s |
HashLib | FNV | 314.92 MB/s |
HashLib | FNV1a | 315.72 MB/s |
HashLib | FNV1a64 | 153.58 MB/s |
HashLib | FNV64 | 143.80 MB/s |
HashLib | Fugue224 | 7.83 MB/s |
HashLib | Fugue256 | 11.12 MB/s |
HashLib | Fugue384 | 10.76 MB/s |
HashLib | Fugue512 | 9.45 MB/s |
HashLib | Gost | 30.68 MB/s |
HashLib | Groestl224 | 9.53 MB/s |
HashLib | Groestl256 | 12.78 MB/s |
HashLib | Groestl384 | 10.68 MB/s |
HashLib | Groestl512 | 14.83 MB/s |
HashLib | Hamsi224 | 10.52 MB/s |
HashLib | Hamsi256 | 10.78 MB/s |
HashLib | Hamsi384 | 4.62 MB/s |
HashLib | Hamsi512 | 4.74 MB/s |
HashLib | HAS160 | 66.54 MB/s |
HashLib | Haval_3_128 | 99.12 MB/s |
HashLib | Haval_3_160 | 211.42 MB/s |
HashLib | Haval_3_192 | 216.02 MB/s |
HashLib | Haval_3_224 | 219.34 MB/s |
HashLib | Haval_3_256 | 208.38 MB/s |
HashLib | Haval_4_128 | 82.46 MB/s |
HashLib | Haval_4_160 | 152.72 MB/s |
HashLib | Haval_4_192 | 153.54 MB/s |
HashLib | Haval_4_224 | 154.21 MB/s |
HashLib | Haval_4_256 | 154.10 MB/s |
HashLib | Haval_5_128 | 69.50 MB/s |
HashLib | Haval_5_160 | 134.36 MB/s |
HashLib | Haval_5_192 | 135.12 MB/s |
HashLib | Haval_5_224 | 134.32 MB/s |
HashLib | Haval_5_256 | 136.45 MB/s |
HashLib | Jenkins3 | 248.97 MB/s |
HashLib | JH224 | 13.28 MB/s |
HashLib | JH256 | 14.31 MB/s |
HashLib | JH384 | 14.32 MB/s |
HashLib | JH512 | 14.32 MB/s |
HashLib | JS | 268.18 MB/s |
HashLib | Keccak224 | 12.40 MB/s |
HashLib | Keccak256 | 13.35 MB/s |
HashLib | Keccak384 | 10.26 MB/s |
HashLib | Keccak512 | 7.19 MB/s |
HashLib | Luffa224 | 23.78 MB/s |
HashLib | Luffa256 | 25.61 MB/s |
HashLib | Luffa384 | 15.39 MB/s |
HashLib | Luffa512 | 11.00 MB/s |
HashLib | MD2 | 8.63 MB/s |
HashLib | MD4 | 166.40 MB/s |
HashLib | MD5 | 145.34 MB/s |
HashLib | Murmur2 | 666.45 MB/s |
HashLib | Murmur2_64 | 231.18 MB/s |
HashLib | OneAtTime | 142.31 MB/s |
HashLib | PJW | 166.14 MB/s |
HashLib | RIPEMD128 | 78.89 MB/s |
HashLib | RIPEMD160 | 58.07 MB/s |
HashLib | RIPEMD256 | 81.01 MB/s |
HashLib | RIPEMD320 | 56.52 MB/s |
HashLib | Rotating | 285.38 MB/s |
HashLib | RS | 311.40 MB/s |
HashLib | SDBM | 241.92 MB/s |
HashLib | SHA1 | 67.83 MB/s |
HashLib | SHA224 | 41.36 MB/s |
HashLib | SHA256 | 43.24 MB/s |
HashLib | SHA384 | 34.62 MB/s |
HashLib | SHA512 | 37.03 MB/s |
HashLib | Shabal224 | 59.56 MB/s |
HashLib | Shabal256 | 127.32 MB/s |
HashLib | Shabal384 | 128.95 MB/s |
HashLib | Shabal512 | 129.63 MB/s |
HashLib | SHAvite3_224 | 25.26 MB/s |
HashLib | SHAvite3_256 | 37.40 MB/s |
HashLib | SHAvite3_384 | 8.26 MB/s |
HashLib | SHAvite3_512 | 10.55 MB/s |
HashLib | ShiftAndXor | 260.40 MB/s |
HashLib | SIMD224 | 7.56 MB/s |
HashLib | SIMD256 | 7.94 MB/s |
HashLib | SIMD384 | 6.73 MB/s |
HashLib | SIMD512 | 7.21 MB/s |
HashLib | Skein224 | 40.09 MB/s |
HashLib | Skein256 | 51.61 MB/s |
HashLib | Skein384 | 51.63 MB/s |
HashLib | Skein512 | 51.77 MB/s |
HashLib | Snefru_4_128 | 26.63 MB/s |
HashLib | Snefru_4_256 | 18.84 MB/s |
HashLib | Snefru_8_128 | 14.80 MB/s |
HashLib | Snefru_8_256 | 9.88 MB/s |
HashLib | SuperFast | 611.25 MB/s |
HashLib | Tiger_3_192 | 62.44 MB/s |
HashLib | Tiger_4_192 | 64.97 MB/s |
HashLib | Tiger2 | 66.68 MB/s |
HashLib | Whirlpool | 7.10 MB/s |
RS Chat v5 April 4th, 2014
Being in the second year of my B.Sc. studies, the Networking class had an assignment to create a simple chat application. While I could've easily turned in any of the earlier versions, I decided to implement a new one in Qt and C++.
The application has an architecture similar to the previous version. Since this application was never published outside of the class assignment, I never ended up creating a page for it and fully documenting it.