How to handle the IV/Nonce/Counter for AES CTR?

不想你离开。 提交于 2019-12-21 06:16:34

问题


import javax.crypto.Cipher;

public abstract class Crypto {


    private static final String CIPHER_ALGORITHM = "AES/CTR/NoPadding";
    private String AesKeyString = "ByWelFHCgFqivFZrWs89LQ==";

    private void setKey() throws NoSuchAlgorithmException{
        byte[] keyBytes;
        keyBytes = Base64.getDecoder().decode(AesKeyString);
        aesKey = new SecretKeySpec(keyBytes, "AES");
    }

    protected byte[] execute(int mode, byte[] target, byte[] iv) 
            throws Exception{
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(mode, aesKey, ivSpec);
        return cipher.doFinal(target);
    }

}

According to NIST Recommendation - Appendix B, there are two valid approaches to construct the initial counter blocks (AES is a 128-bit block cipher):

  1. 128-bit nonce XORed with an m-bit counter value (usually 32 bits).
  2. 64-bit nonce prepended to a 64-bit counter.

My question is:

  • What is the exact procedure regarding the initial counter block used in an "AES/CTR/NoPadding" instance of javax.crypto.Cipher (assuming SunJCE as the provider)? That is, given the above code, which of the previous approaches for the initial counter block is used, if any?

回答1:


Java simply leaves the choice of the way you construct the counter to you. You simply have to initialize the CTR mode using a 16 byte IV, which is nothing more than the initial counter value.

Once you start encrypting it will use a counter over the full 128 bits. Then again, you would hardly want it to start over as that would directly compromise the security of the plaintext. The disadvantage is that the 32 bit XOR method is not directly supported (if you start with a a counter of FFFFFFFF the next value will alter the 33rd least significant bit of the counter).

Then again, I would rather choose a 8-byte nonce and leave the least significant bits set to all zeros. Or choose GCM mode of course.


Proof:

Cipher aesCTR = Cipher.getInstance("AES/CTR/NoPadding");
SecretKey aesKey = new SecretKeySpec(new byte[16], "AES");
IvParameterSpec lastIV = new IvParameterSpec(Hex.decode("FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF"));
aesCTR.init(Cipher.ENCRYPT_MODE, aesKey, lastIV);
byte[] twoBlocks = aesCTR.doFinal(new byte[2 * aesCTR.getBlockSize()]);
byte[] secondBlock = Arrays.copyOfRange(twoBlocks, 16, 32);
System.out.printf("%s%n", Hex.toHexString(secondBlock));

IvParameterSpec firstIV = new IvParameterSpec(new byte[16]); // all zero IV
aesCTR.init(Cipher.ENCRYPT_MODE, aesKey, firstIV);
byte[] oneBlock = aesCTR.doFinal(new byte[aesCTR.getBlockSize()]);
System.out.printf("%s%n", Hex.toHexString(oneBlock));

Output:

66e94bd4ef8a2c3b884cfa59ca342b2e
66e94bd4ef8a2c3b884cfa59ca342b2e


来源:https://stackoverflow.com/questions/42836844/how-to-handle-the-iv-nonce-counter-for-aes-ctr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!