1
$\begingroup$

I need to encrypt 20 bytes of data and the encrypted nonce + data + mac cannot exceed 30 bytes in size. I have an implementation but i'm not sure if i'm cutting too many corners and compromising encryption.

Using the bouncy castle library i was able to write this.

    static (byte[],byte[]) encrypt(byte[] data, byte[] key, byte[] nonce)
    {
        var engine = new AesEngine();
        var parm = new AeadParameters(new KeyParameter(key), 16, nonce);
        var chipher = new CcmBlockCipher(engine);
        chipher.Init(true, parm);

        var output = new byte[chipher.GetOutputSize(data.Length)];
        var outputLength = chipher.ProcessBytes(data, 0, data.Length, output, 0);
        chipher.DoFinal(output, outputLength);

        return (output, chipher.GetMac());
    }

Here is my thinking. For the data encrypted i have the following pieces of information known:

  • Metadata about the origination of the data
  • The approximate date the data was encrypted (down to the day)

With that information i formulated a nonce that contains:

2 bytes meta + 8 bytes Unix ms timestamp

With that i'm able to chop off all but the last 4 bytes of the nonce as those are the least significant bytes that indicate a timestamp for the day in question.

With that in mind i can have the final full encoded data as:

4 byte nonce + 20 byte encrypted + 2 byte MAC

This makes it fit under the 30 byte limit.

So here are my questions:

  1. Is a 16 bit MAC effective at all in this scenario?
  2. Is it kosher to create a nonce from partially known data?
  3. How can i verify that my nonce is being incremented properly inside the code? I just appear to pass a static nonce even though its supposed to increment according to CTR... right?
$\endgroup$
0
$\begingroup$

So I'll answer in order:

Q1: Is a 16 bit MAC effective at all in this scenario?

You have defined (part of) your protocol, but you haven't defined your system. What happens if a MAC doesn't get accepted? If you have only a 16 bit MAC then there are only 65536 values of the MAC. If an adversary can just generate messages and fire them at the receiver then brute forcing a tag is entirely possible. Even if you can just have one try: a chance of $1 \over 65536$ is not considered secure enough.

Using 8 bytes would be a great idea, but that leaves you only 2 bytes for a nonce, so you would only have 65536 messages.

Q2: Is it kosher to create a nonce from partially known data?

Sure thing, a Nonce just needs to be unique - but note that in the case of CTR and CCM the nonce size also influences how many counter blocks can be created, and therefore how much data can be processed per nonce. CCM is just like CTR in that sense; it even requires an additional byte of meta information in the counter, leaving less space for the nonce and counter.

Kind of obvious, but the other requirement is that the receiver must be able to re-generate the nonce.

Q3: How can i verify that my nonce is being incremented properly inside the code? I just appear to pass a static nonce even though its supposed to increment according to CTR... right?

No, the counter is being incremented - not the nonce. The nonce is just used to create the counter. Often the nonce is simply the most significant part of the counter. In the case of CCM this is true as well, even though the most significant byte is skipped. see for instance NIST SP 800-38C chapter A.3 where the counter increase is being implemented.

In GCM mode it is also possible that the nonce is pre-processed to generate the initial counter value, so there are certainly differences in how the nonce is used between the various implementations of authenticated encryption, even though CTR mode is used in virtually all these modes.

Note that the counter mode specified by NIST does not specify how the counter value must be generated; implementations are free to choose any scheme they want.

$\endgroup$
  • $\begingroup$ I'm wondering a bit about the Bouncy Castle implementation though: the nonce should certainly be smaller than 16 bytes, $\endgroup$ – Maarten Bodewes Dec 5 '17 at 21:38
  • $\begingroup$ Ah.... throw new IllegalArgumentException("nonce must have length from 7 to 13 octets"); $\endgroup$ – Maarten Bodewes Dec 5 '17 at 21:43
  • $\begingroup$ During testing i was just using 8 bytes timestamp but figured i'd expand it to use the meta data. Sorry for the confusion. Is there any need to add at least some part of the meta to make the nonce truly unique to the unit generating the data or is that just gravy? $\endgroup$ – Chris Rice Dec 5 '17 at 21:46
  • $\begingroup$ I don't know how the CCM mode is used in your system, so I can only speculate what makes a unique nonce. However, if it is not unique CCM - and any other authentication mode that uses CTR mode underneath - will fail spectacularly - except for SIV mode where the IV is dependent on the message & authenticated data as well (so the nonce + message & authenticated data must be unique). $\endgroup$ – Maarten Bodewes Dec 5 '17 at 22:10

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.