Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java AES CTR IV and counter

I have tried to find the answer by myself looking here and searching elsewhere for quite a while, but I still have some questions.

Assume this Java code:

try
{   
    int cipherMode = Cipher.ENCRYPT_MODE;

    SecretKeySpec secretKey = ...; // generated previously using KeyGenerator       

    byte[] nonceAndCounter = new byte[16];
    byte[] nonceBytes      = ...; // generated previously using SecureRandom's nextBytes(8);

    // use first 8 bytes as nonce
    Arrays.fill(nonceAndCounter, (byte) 0);
    System.arraycopy(nonceBytes, 0, nonceAndCounter, 0, 8);

    IvParameterSpec ivSpec = new IvParameterSpec(nonceAndCounter);
    Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

    cipher.init(cipherMode, secretKey, ivSpec);

    File inFile  = new File(...);
    File outFile = new File(...);

    long bytesRead = 0;

    try (FileInputStream is = new FileInputStream(inFile);
         FileOutputStream os = new FileOutputStream(outFile))
    {       
        byte[] inBuf       = new byte[512 * 1024];
        byte[] outBuf      = new byte[512 * 1024];
        int    readLen     = 0;

        ByteBuffer byteBuffer = ByteBuffer.allocate(8);
        byteBuffer.putLong(bytesRead);

        while ((readLen = is.read(inBuf)) != -1)
        {
            bytesRead += readLen;

            cipher.update(inBuf, 0, readLen, outBuf, 0);

            os.write(outBuf);
        }

        cipher.doFinal(outBuf, 0);
        os.write(outBuf);
        is.close();
        os.close();
    }
    catch (Exception e) {
        System.out.printf("Exception for file: %s\n", e);
    }
} 
catch (Exception e) { 
    System.out.printf("Exception: %s\n", e);
}

My questions are:

  1. Is the above code considered OK regarding counter updates for CTR mode? Specifically, I am not updating the counter myself. Should I use the following while loop instead? I tried this because I looked at what cipher.getIV() returns in the loop, but it does not change and the description for getIV() does not go into much details:

        while ((readLen = is.read(inBuf)) != -1)
        {   
            // use offset for last 8 bytes as counter
            byteBuffer.putLong(bytesRead);
            System.arraycopy(byteBuffer.array(), 0, nonceAndCounter, 8, 8);
    
            bytesRead += readLen;
    
            IvParameterSpec ivSpec = new IvParameterSpec(nonceAndCounter);
    
            cipher.init(cipherMode, secretKey, ivSpec);
    
            cipher.update(inBuf, 0, readLen, outBuf, 0);
    
            os.write(outBuf);
        }
    
    1. I have more questions related to the modified while loop approach. Is it OK to call cipher.init() in such a way? I do this because I haven't found a way to update just IV (counter really).

    2. Is such a large block size OK or should it be made smaller? In that case how big should it be?

like image 211
jarok Avatar asked Jul 20 '17 09:07

jarok


People also ask

What is key and IV in AES?

AES algorithm requires two different parameters for encryption, a key and an initialization vector (IV). I see three choices for creating the key file: Embed hard-coded IV within the application and save the key in the key file. Embed hard-coded key within the application and save the IV in the key file.

When implementing AES with Java What is an IV?

When using AES with a mode known as CBC (Cipher Block Chaining), you need to generate an initialization vector (IV). In the CBC mode, each plaintext block is XORed with the previous ciphertext block before being encrypted. So you need an initialization vector for the first block.

Does AES CBC require IV?

CBC requires a random IV for each encryption. The IVs are therefore completely uncorrelated to the plaintexts or the keys; so knowledge of the IV reveals no information about the plaintext.

What is CTR AES?

CTR (short for counter) is a popular AES block cipher mode in which every step can be done in parallel. CTR is similar to OFB as it also involves XOR-ing a sequence of pad vectors with the plaintext and ciphertext blocks. The main difference lies in how these pad vectors are generated.


1 Answers

  1. Is the above code considered OK regarding counter updates for CTR mode?

Yes.

But you might want to tweak the nonce and counter sizes a bit. If your nonce is only 64 bit long, you'll likely run into a nonce collision after 232 encryptions due to the birthday paradox (the probability is increasing if you approach that point). If you use the same key for all of these encryptions (I mean messages/files not blocks) and there is a collision, this is considered a catastrophic break for CTR-mode, because it is a two-time or many-time pad.

You should consider using a 96 bit nonce and a 32 bit counter. The disadvantage is that you can only encrypt up to 232 blocks safely which is something like 68 GB per message/file.

  1. I have more questions related to the modified while loop approach. Is it OK to call cipher.init() in such a way?

No.

You really should not update the counter yourself. Note that you have a mismatch between bytes and block cipher blocks: Your proposed counter update uses the bytes that were already processed as a fresh counter value which advances much quicker than the natural CTR mode counter which counts block-wise. You're exhausting the counters so that a collision is getting more probable. For example, if the nonces differ by 1 when represented numerically, then an overlap might occur if the nonce part is short and the counter part is long. If the nonce is 96 bit long then you can only encrypt messages/files with a size of 68/16 GB = 4.5 GB safely.

Also, since you have a byte/block mismatch, this is not CTR mode anymore and you will have a hard time to port this code to other languages.

  1. Is such a large block size OK or should it be made smaller? In that case how big should it be?

Not sure what you mean, AES has a fixed block size of 128 bit or 16 byte.

If you mean the input/output buffers, then you should benchmark it on your platform of choice to be sure. It certainly looks OK.

like image 100
Artjom B. Avatar answered Sep 23 '22 07:09

Artjom B.