簡體   English   中英

Java AES CTR IV和計數器

[英]Java AES CTR IV and counter

我試着找到答案,自己看這里並在別處搜索了一段時間,但我還是有一些問題。

假設這個Java代碼:

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);
}

我的問題是:

  1. 對於CTR模式的計數器更新,上述代碼是否正常? 具體來說,我不是自己更新計數器。 我應該使用以下while循環嗎? 我試過這個是因為我查看了cipher.getIV()在循環中返回的內容,但它沒有改變,getIV()的描述沒有詳細說明:

      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. 我有更多與修改的while循環方法有關的問題。 以這種方式調用cipher.init()可以嗎? 我這樣做是因為我還沒有找到一種方法來更新IV(計數器真的)。

    2. 是如此大的塊大小還是應該變小? 在那種情況下它應該有多大?

  1. 對於CTR模式的計數器更新,上述代碼是否正常?

是。

但是你可能想要調整一下nonce和counter大小。 如果你的nonce只有64位長,那么由於生日悖論,你可能會在2 32次加密后遇到nonce沖突(如果接近那個點,概率會增加)。 如果你對所有這些加密使用相同的密鑰(我的意思是消息/文件不是塊)並且存在沖突,這被認為是CTR模式的災難性中斷,因為它是兩次或多次填充。

您應該考慮使用96位隨機數和32位計數器。 缺點是您最多只能安全加密2 個32塊,每個消息/文件大小為68 GB。

  1. 我有更多與修改的while循環方法有關的問題。 以這種方式調用cipher.init()可以嗎?

沒有。

你真的不應該自己更新計數器。 請注意,字節和塊密碼塊之間存在不匹配:建議的計數器更新使用已作為新計數器值處理的字節,其速度比按塊計數的自然CTR模式計數器快得多。 你正在耗盡計數器,以便更容易發生碰撞。 例如,如果在數字表示時,隨機數相差1,則如果nonce部分較短且計數器部分較長,則可能發生重疊。 如果nonce是96位長,那么你只能安全地加密大小為68/16 GB = 4.5 GB的消息/文件。

此外,由於您的字節/塊不匹配,這不再是CTR模式,您將很難將此代碼移植到其他語言。

  1. 是如此大的塊大小還是應該變小? 在那種情況下它應該有多大?

不確定你的意思,AES的固定塊大小為128位或16字節。

如果您的意思是輸入/輸出緩沖區,那么您應該在您選擇的平台上對其進行基准測試以確定。 它當然看起來不錯。

而不是像你在這里那樣生成iv / nonce:

// 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);

您應該考慮執行以下操作:

Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
// By doing this here w/o an IvParameterSpec, you let the
// cipher initialization create it. Less chance (see what I did there)
// to influence values that should be completely random.
cipher.init(cipherMode, secretKey);
AlgorithmParameters ivSpec = cipher.getParameters();
byte[] nonceAndCounter= ivSpec.getEncoded()

在接收端,當您需要從返回到nonceAndCounter的值構造IvParameterSpec時,然后構建您的解密模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM