I am following a wiki diagram for CTR mode of operation in AES256. The documentation states that for it to work you need a random nonce with 8 bytes and then a counter of 8 bytes. So I guess you can randomly generate nonce for instance: SgVkYp3s. And then you just add a count to it. Then you iterate over all of your plaintext bytes and up the count with every pass of the for a loop. So in the end you get nonce like SgVkYp3s00000000, SgVkYp3s00000001, ... And then you use the same format for decryption. Is this the correct approach?
-
$\begingroup$ "SgVkYp3s" in what base is that a number? $\endgroup$– MaeherDec 11, 2020 at 16:26
-
$\begingroup$ Whats the problem with that? Oh and the string used is just randomly generated so i could ask this question. Where i read the requirements for the joined nonce and counter is that the first 64 bits are random and the last 64 bits are counter. $\endgroup$– znoris007Dec 11, 2020 at 16:51
1 Answer
The counter mode encryption (and similarly the decryption) with AES work as
$$C_i = AES(key,nonce,i) \oplus m[i]$$ where the nonce and index $i$ is used to encrypt the $i$th block with the x-or of the output of the encryption.
The cryptographic algorithms work on bytes and you can consider it as a byte array. Now you need to fill the byte array with your random 8-byte values on the lower index and the rest is set to 0.
If you want to have the random access that CTR enables, you can set the upper bytes to the index $i$ within 64-bit representation.
If you are encrypting sequentially, then after setting the counterpart to zero, you need to implement a byte array incrementer. If we represent in hex then we need two hex char per byte;
1b4fe8364as4a8100000000000000000 //initial
1b4fe8364as4a8100000000000000001 //counter incremented
1b4fe8364as4a8100000000000000002 //counter incremented
1b4fe8364as4a8100000000000000003 //counter incremented
..
1b4fe8364as4a81000000000000000FF //counter incremented
...
So I guess you can randomly generate nonce
There is a common problem here, 64-bit nonce is vulnerable to collisions. After $2^{32}$ random nonce generation under the same key one will have collisions with 50%. The 50% is not negligible, one must stop way before that. A better way is either
- Generate the nonce sequentially, which may some other problems as system failures can cause re-use of the old values were the easiest mitigation is using a fresh key. Or,
- Use larger random like AES-GCM uses; 96-bit nonce. This is safer to use randomly. Keep in mind that, this will limit the number of block encryption to $2^{32}$ and this makes $2^{36}$ bytes and that is $\approx 68.71$ GB.
And remember, AES has a 128-bit block size regardless of its key sizes 128, 192, and 256.
Normally, the cryptographic libraries handle those parts for you. You don't need to worry about those like Java's IvParameterSpec.