In a current project the NaCl-library crypto_box function has been used to encode and crypto_box_open to authenticate and decode data.

However the library does not seem to support de- / encoding of large amounts of data, since the message and the buffer for the cipher text (plus nonce) as well have to be allocated in memory (The application has to run on smartphones and therefore must not consume too much memory).

Reading the documentation I came across the crypto_stream_xor function which may allow to encrypt custom-sized portions of data, for example delivered through a stream. However a MAC still needs to be generated to detect message tampering.

Is there any built in way to generate and verify the MAC on a large message m or has this to be dealt with on an upper level of communication by splitting large amounts of data in several authenticated, encrypted packages?

  • The latter should be preferred. You should not process unauthenticated data. The only place where you should decrypt huge packages of data is where you 1) don't process the data immediately and 2) you cannot store the data in RAM. A good example would be file encryption/decryption. Even then it may pay off to split the plaintext into blocks or fragments. – Maarten Bodewes May 26 '15 at 2:29
  • 4
    You could always mmap() files and use the NaCL functions as is. – Celada May 27 '15 at 17:30
  • @MaartenBodewes Thanks for your input. I'm trying to find another way without splitting up the plain data in several encrypted blocks. Celada's mmap() approach seems promising, since it is transparent to the calling functions. However I'm not sure how reliable this function is on Android / iOS devices. – Lukas May 28 '15 at 8:01
  • Android has been derived from Linux and iOS from BSD if I'm not mistaken. I don't see why mmap should have issues but it never hurts to test. Of course you would need native code to use mmap. Java has also java.nio but I'm not sure you could use that for this use case. – Maarten Bodewes May 28 '15 at 8:38
  • That mmap() behavior is guaranteed by POSIX. It will be reliable on any compliant system. – forest Nov 30 '17 at 3:10

The NaCl API is designed to work on an entire message at a time for a reason: The largest message you are willing to handle is the largest amount of memory that an attacker can waste in a denial of service attack on the receiver of the message. You probably want to limit this to something small like a single IP packet, or a single megabyte, or similar.

You should break your data up into smaller pieces, and authenticate them in order, e.g. with the piece sequence number or byte offset figured into the nonce or associated data. The overhead of an authentication tag is a mere 16 bytes, which is trifling in comparison to a megabyte of data.

Although this means you can confidently act on each piece of data in your pile as soon as you have verified it, doing so also means that you have to be able to handle truncation of the data partway through. (But it's better to merely have to deal with truncation than to be tempted to operate on unauthenticated data, which is pure evil—don't touch it!)

There are some existing generic systems for authenticated encryption of streams, like miscreant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.