简体   繁体   中英

Symmetric encryption in C# from byte-array to byte-array without streams

Is there any way of using a decent symmetric encryption from the .Net (maybe I missed something) to achieve the encryption of a source byte array to a destination byte array (both pre-allocated)? Or I have to look or code a custom AES encryption system?

The reason I need byte array to byte-array is explained below:

I'm working on adding encryption to an existing C# Socket based server. The server uses Socket.Select to handle very large amounts of non-blocking client sockets which send from time to time relatively small chunks of data on very few threads. Also the server is highly optimized speed and memory allocation wise. The server is built around the idea of sending and receiving chunks of data of maximum 16k bytes (usually only a few hundreds are actually exchanged and very rarely 1-2k). All these chunks are re-used to avoid allocations.

I've tried using .Net's SslStream, but I can't find a way to use it without many threads or the .Net async/begin-end mechanisms - which seem to choke at about 100+ clients (depending on os and machine power). With the SslStream I was able to use the server's allocated memory chunks, but I can't use the Socket.Select in a safe way because of the streams involved (tcp and ssl).

My next step was to try and implement the SSL socket by hand. I can transmit the server's public key to the clients, there I generate a new symmetric key with RijndaelManaged, which I then encrypt using the server's public key and send it back to the server. Everything works great, but I can't find a way to use the RijndaelManaged encryption without it's ICryptoTransform which has 2 issues: I have to create a lot of ICryptoTransform with the CreateEncryptor (resulting in memory mess) and also it generates a new byte array after each encryption resulting in more work for the GC.

The actual crypto operations performed by TLS after the handshake consists of symmetric encryption of the plaintext and validation of an authentication tag. Now this are exactly the operations that you do have to implement anyway to have any decent amount of security.

Of course there are ways to speed up these operations. Basically there are two ways:

  1. hardware support for used algorithms, eg use a TLS provider that uses AES-NI and other hardware instructions;
  2. algorithms that are fast within software.

Besides - of course - optimizing the software implementation itself. Managed languages such as C# or Java (which it of course is largely based on) are not very fast when it comes to implementing the many loops / shifts etc. in a cipher that basically has been created to run fast on a real CPU. Using RijndaelManaged is probably not the best way to go (did you know there is an AES.Create function?).


But let's focus on the two listed methods.

TLS providers may already use hardware instructions, but you might make sure that your providers and platform are indeed written to support them.

Another way of making the encryption / decryption be fast is to switch to software algorithms such as Salsa20 / Poly1305, a scheme for authenticated encryption that has been brought to TLS starting with 1.2, backed by Google.


The latest version of the TLS protocol - at the time of writing - is TLS 1.3. TLS 1.3 has many methods to make the handshake more performant. Actually, if a previous secret was established it may skip it altogether. That may really help if there are many connections made rather than much data transported. So if you want to have top-notch security you might want to require TLS 1.3 and optimize for that.


And if you have done this and failed, then you can always put a TLS end point such as an actual TLS accelerator in front of your machine and simply use that. Java architectures often run on Apache Tomcat or a derived application server with a Apache webserver - configured as a proxy - in front of it. The connectors in between even send out information about the TLS connection when it is made to the application server. There are also separate hardware products that offer this kind of service, and they'll support many more TLS streams then you'll ever need, if you are prepared to spend the $$$ and the time to configure them correctly (key / certificate management).


here are certainly protocols that have different target audiences than TLS, which is a rather complicated protocol. You might be better off with a DTLS implementation, or a protocol that was created for embedded devices. But prepare for a steep learning curve and lots of work if you go into that direction.

So all in all, I would not go looking for a fast alternative to TLS, as any alternative basically has to perform the same operations . Speeding up TLS is probably a better option. What you certainly should not do is to create your own protocol and implementing TLS yourself should only be performed if you have enough experience with the subject - there are just too many pitfalls when creating transport protocol implementations.

经过大量研究,我改变了服务器处理请求的方式(基本上删除了.net中的SSL / TLS支持),并且我们正在尝试在.net服务器之前使用TLS终止代理,该代理将处理所有繁重的tls事务。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM