0

In my project I am using Libsodium, in particular I am using the stream cryptography,trying it out gave me a few questions:

Nonce:

  • What is it?
  • What is it for?
  • Does it have to be secret for the security of the message?

Header:

unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
  • What is it?
  • What is it for?
  • What does it contain?
  • Does it have to be secret for the security of the message?

State:

crypto_secretstream_xchacha20poly1305_state state;
  • What is it?
  • What is it for?

In the documentation you can see 2 examples

The first concerns 2 functions, one for encrypting and the other for decrypting a file, what it does in brief is:

Function to encrypt:

  1. Open the original file and the target file.
  2. You initialise a state
  3. You first write the header inside the target file
  4. A loop is repeated until the end of the original file in which a block of the file is encrypted and the product is written into the target file.

Function to decrypt:

  1. Open the original file and the target file.
  2. You initialise a state
  3. The header is read and stored in a variable.
  4. A loop is repeated until the end of the original file where a block is taken, decrypted and the product is written to the target file.

The second example only concerns an encryption with a subsequent decryption of a message stream.

The difference between the two examples, apart from being in the fact that one concerns files while the other only concerns a message stream, lies in the fact that in the first example the header is stored in a file and then in the decryption it is read, while in the message stream it is not stored anywhere, so if the encryption and decryption phases were separated it would no longer work.

So in the case of the message stream, be it several messages OR JUST ONE, where do I put the header?

Adam
  • 11
  • 4
  • Is this the problem: https://stackoverflow.com/q/2950332 – Artyer Aug 16 '22 at 09:30
  • @Artyer i have changed my question, can you look? – Adam Aug 16 '22 at 11:40
  • 1
    A "nonce" is something that is used once and discarded. It is used to add randomness to a message, so an attacker can't guess your key by looking for a common header in your encrypted messages, for example. The header is used to store information required to decrypt. For example, it might store the number of bits in the key or the size of the factors. – Tim Roberts Aug 16 '22 at 22:59
  • @TimRoberts, thank you. Hedear must be secret for the security of the message? – Adam Aug 17 '22 at 08:48
  • No, I don't think the header itself is encrypted, because that information is needed in order to decrypt. – Tim Roberts Aug 17 '22 at 16:33
  • @TimRoberts, Does the Header have a constant size? – Adam Aug 17 '22 at 21:58
  • You can see that in your code: it is `crypto_secretstream_xchacha20poly1305_HEADERBYTES` long. If you check the source, that's 24 bytes. – Tim Roberts Aug 17 '22 at 22:10

1 Answers1

0

Nonce:

  • A nonce is a (usually short) value that must be unique for every message. Using the same nonce to encrypt two different messages can completely break the security of a cryptosystem. Because of this, libsodium's crypto_secretstream API does not require (or allow) you to provide a nonce. Libsodium will handle that automatically (by picking a random nonce).
  • What is it for? It prevents messages encrypted with the same key from being dangerously similar.
  • Does it have to be secret for the security of the message? No. If it had to be secret it would be part of the key.

Header:

  • What is it for? It contains the data that libsodium needs to decrypt the stream (other than the key). e.g. it includes the nonce.
  • Does it have to be secret for the security of the message? No. It is normally prepended to the encrypted message.

State:

  • What is it for? This is a structure that contains whatever data libsodium needs during the encryption or decryption process. It must not be included as part of the message and should be wiped/discarded when you are finished encrypting/decrypting the stream.

The second example you mention is skipping the entire process of transmitting the header and encrypted blocks to the program that will decrypt them, because that process will be specific to each application. It is your responsibility to handle that.

In particular, it is your responsibility to know the size of each encrypted block, because you must pass each block in its entirety. You can do this by either using a fixed block size, or by sending the size of each block along with the block. That is, each block returned by crypto_secretstream_xchacha20poly1305_push must be passed to crypto_secretstream_xchacha20poly1305_pull in the same order. You must not split them up, reorder them, or combine them. If you do, the decryption will fail.

cjm
  • 61,471
  • 9
  • 126
  • 175