29

I am having an application where I have to send several small data per second through the network using UDP. The application needs to send the data in real-time (no waiting). I want to encrypt these data and ensure that what I am doing is as secure as possible.

Since I am using UDP, there is no way to use SSL/TLS, so I have to encrypt each packet alone since the protocol is connectionless/unreliable/unregulated.

Right now, I am using a 128-bit key derived from a passphrase from the user, and AES in CBC mode (PBE using AES-CBC). I decided to use a random salt with the passphrase to derive the 128-bit key (prevent dictionary attack on the passphrase), and of course use IVs (to prevent statistical analysis for packets).

However I am concerned about few things: Each packet contains small amount of data (like a couple of integer values per packet) which will make the encrypted packets vulnerable to known-plaintext attacks (which will result in making it easier to crack the key). Also, since the encryption key is derived from a passphrase, this will make the key space way smaller (I know the salt will help, but I have to send the salt through the network once and anyone can get it). Given these two things, anyone can sniff and store the sent data, and try to crack the key. Although this process might take some time, once the key is cracked all the stored data will be decrypted, which will be a real problem for my application.

So my question is, what are the best practices for sending/encrypting continuous small data using a connectionless protocol (UDP)? Is my way the best way to do it? ...flowed? ...Overkill?

Please note that I am not asking for a 100% secure solution, as there is no such thing.

artburkart
  • 1,830
  • 1
  • 20
  • 28
temp
  • 485
  • 2
  • 5
  • 7
  • Just as a notice: as today (5.12.2014), Spark Core is using AES-128-CBC when communicating with server (cloud). It pings server at least once every 15 seconds with ~8bytes message which after encryption takes 2+128bytes. When the user decides to send/recaive more data it accumulates quickly (especially on 3G). – Paweł Szczur Dec 05 '14 at 12:31
  • Disclaimer, I am not a security expert. DTLS is a standard option. But as a basic idea for a custom protocol, you can exchange first symmetric key and encryption algorithm using asymmetric key (use TLS); use symmetric key for further datagrams; change this symmetric key periodically by appending new key to data. Key renewal causes minimum overhead, unpredictable data (works like salt), and there is not enough time to crack your key. – S.M.Mousavi Jul 04 '21 at 07:29
  • Also look at CoAP. It is a simple application layer protocol on top of UDP for IoT and especially designed for small packet which supports both connectionless and connection oriented communications and has an observer mechanism for situations like yours. Another option could be MQTT. Both of these protocols supports encryption. – S.M.Mousavi Jul 04 '21 at 07:38

7 Answers7

19

You have several choices. You can use DTLS, which is a version of TLS adapated for datagrams. It is specified in an RFC and implemented in the openssl library. You can also use the IKE/IPsec protocol and use a UDP encapsulation of the IPsec portion. Usually IPsec is available at the OS level. You can also use OpenVPN, which looks to be a hybrid of TLS for key exchange and a proprietary UDP-based packet encryption protocol.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • DTLS/IPSec are interesting protocols for my problem. They might help in the strengthening key generation but I doubt they will do anything about small data problem, which I should handle by myself. I will explore them more. Thanks – temp Jun 19 '10 at 13:16
  • I'm not too clear and what exactly the "small data" problem is, but yet another choice is to use the SRTP protocol, RFC 3711. DTLS for key management and SRTP for the data (RFC 5764) is the IETF choice for secure VoIP, and that has many small frames going back and forth. – President James K. Polk Jun 19 '10 at 13:37
  • 2
    @temp What is the "small data problem"? If your packets are so small that they limit entropy, the only way that it can compromise security is if your server reports back in a way that can give the attacker information about whether it has succeeded in guessing the right value. The solution to that is to never issue responses that provide that sort of information to untrusted clients until accumulating sufficient input at all times. Whether this is difficult or trivial depends on your application of course. Also Amnon's suggestion of padding also works; slightly more wasteful. – Steven Lu Apr 03 '13 at 22:36
4

If your problem is that the data is too small, how about extending the data with random bytes? This will make the plaintext much harder to guess.

Amnon
  • 7,652
  • 2
  • 26
  • 34
  • Yes you are right. I thought about this but didn't mention it above as I didn't implement it yet. I will see what others suggests. – temp Jun 14 '10 at 19:25
  • I am new to encryption but perhaps you could even some tactic to randomize the *location(s)* of the random bytes too, and when the client reads the packet's data it can easily figure out which bytes to skip over, but perhaps it will increase the difficulty of an outsider trying to analyze the encrypted data. – rsethc Dec 08 '16 at 13:29
1

This question is a little old, but what about using a One Time Pad type approach? You could use a secure reliable transport mechanism (like HTTPS) to transmit the one time keys from the server to your client. There could be two sets of keys -- one for client to sever, and one for server to client. Each datagram would then include a sequence number (used to identify the one time key) and then the encrypted message. Because each key is used for only one datagram, you shouldn't be exposed to the small data problem. That said, I'm not an expert at this stuff, so definitely check this idea out before using it...

alarik
  • 54
  • 3
0

Use Ecdh key exchange (use a password to encrypt the client private key; left on the client) instead of a password. This is a very strong key.

Aes cbc does not help you; the messages are too short and you want to prevent replay attacks. Pad your 64 bit message (two integers) with a counter (starting with 0) 64 bits means 2^64 messages can be sent. Encrypt the block twice (aes ecb) and send e(k;m|count)|e(k;e(k;m|count)). Receiver only accepts monotonically increasing counts where the second block is the encryption of the first. These are 32 byte messages that fit fine in a udp packet.

if 2^64 messages is too small; see if your message could be smaller (3 byte integers means the counter can be 80 bits); or go back to step 1 (new private keys for at least one side) once you are close (say 2^64-2^32) to the limit.

Warren MacEvoy
  • 898
  • 9
  • 14
0

You could always generate a fresh pair of IVs and send them alongside the packet.

0

These days a good streaming cipher is the way to go. ChaCha20 uses AES for a key stream. Block ciphers are the ones that need padding.

Still that's only part of the picture. Don't roll your own crypto. DTLS is probably a mature option. Also consider QUIC which is emerging now for general availability on the web.

Kind Contributor
  • 17,547
  • 6
  • 53
  • 70
0

Consider using ECIES Stateless Encryption https://cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme where you sending devices use the public key of the central system and an ephemeral key to generate a symmetric key pair, then a KDF, then AES-256-GCM. You end up with modest size packets which are stateless and complete. No need for an out-of-band key agreement protocol. There are good examples on the internet, for example: https://github.com/insanum/ecies/blob/master/ecies_openssl.c I am using such a system to deliver telemetry from mobile devices over an unsecure channel.

Mike Tubby
  • 41
  • 1
  • 2