2017-03-16 337 views
2
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); 
    } 

} 

根據NIST Recommendation - 附錄B,有構建初始計數器塊(AES是128比特塊密碼)兩種有效的方法:如何處理AES CTR的IV/Nonce/Counter?

  1. 128位的隨機數進行異或運算與位計數器值(通常是32位)。
  2. 將64位隨機數添加到64位計數器。

我的問題是:

  • 什麼是關於初始計數器塊的確切過程在 「AES/CTR/NoPadding」 javax.crypto.Cipher中的實例(假設了SunJCE所用 提供者)? 也就是說,考慮到上述代碼,使用了初始計數器塊的以前方法中的哪一種,如果有的話?
+0

@MaartenBodewes –

+0

這並不僅在我發佈的評論,但嘿地方工作無處不在,沒問題,[Artjom](http://stackoverflow.com/users/1816580/artjom-b)照顧了:) –

回答

1

Java只是讓你選擇構建計數器的方式給你。您只需使用一個16字節的IV來初始化CTR模式,這只不過是初始計數器的值。

一旦開始加密,它將在整個128位上使用一個計數器。再說一次,你很難讓它重新開始,因爲這會直接影響到明文的安全性。缺點是不直接支持32位XOR方法(如果以FFFFFFFF的計數器開始,則下一個值將改變計數器的第33個最低有效位)。

然後,我寧願選擇一個8字節的隨機數,並將最不重要的位設置爲全零。或者當然選擇GCM模式。


證明:

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

輸出:

66e94bd4ef8a2c3b884cfa59ca342b2e 
66e94bd4ef8a2c3b884cfa59ca342b2e