2017-08-05 52 views
-1

我想用AES加密數據,但我不知道爲什麼輸出大於輸入。 我用這個函數來導出密鑰加密數據大於輸入數據

public byte[] deriveKey(String p, byte[] s, int i, int l) throws Exception { 

    PBEKeySpec ks = new PBEKeySpec(p.toCharArray(), s, i, l); 
    SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    return skf.generateSecret(ks).getEncoded(); 
} 

此後我發送其的數據(112個字節)和鍵加密函數,但我得到加密的數據(154個字節)

public String encrypt(String s,byte[] d) throws Exception { 

    // Perform Encryption 
    SecretKeySpec eks = new SecretKeySpec(d, "AES"); 
    Cipher c = Cipher.getInstance("AES/CTR/NoPadding"); 
    c.init(Cipher.ENCRYPT_MODE, eks, new IvParameterSpec(new byte[16])); 
    byte[] es = c.doFinal(s.getBytes(StandardCharsets.UTF_8)); 
} 
+1

加密不是壓縮。根據加密方法,加密結果可以更大或更小。 –

+1

@ישואוהבאותך但不是在OP的情況下。由於他使用的是CTR模式,因此得到的密文應該與明文完全相同的字節長度。 –

+0

你的例子不完整。你加密函數返回一個字符串,但是它的最後一個語句返回一個字節數組。我的猜測是,在返回結果之前,你的base64將對結果進行編碼,這將考慮結果的大小。 –

回答

-1

在許多加密算法中,填充是不可避免的。這就是爲什麼你看到密碼增加的原因。此信息可能有助於您瞭解發生了什麼:https://security.stackexchange.com/questions/29993/aes-cbc-padding-when-the-message-length-is-a-multiple-of-the-block-size

+0

填充需求不是由密碼本身決定的,而是由塊模式決定的。根據定義,CTR模式不需要填充。請注意,在文章中,您使用的模式是CBC,**不是** CTR。 –

+0

提供的代碼沒有填充:'cipher c = Cipher.getInstance(「AES/CTR/NoPadding」);' – rossum

0

要加密明文是一個字符串(s),你加密前右編碼爲一個字節數組:s.getBytes(StandardCharsets.UTF_8)

如果明文字符串包含非ASCII字符(代碼點爲128及以上),那麼這些字符將被編碼爲UTF-8的兩個或多個字節(請參閱Wikipedia article中的表格)。英文文本可能包含與字符相同的字節數。其他語言可能不那麼幸運,並且從字符串到二進制數據的編碼將被炸燬。

CTR模式是一種流式操作模式,所以明文/密文輸入的大小始終與密文/明文輸出的大小相同。問題當然就是像AES-CTR這樣的方案有三個輸入:密鑰,數據和IV /隨機數。

只有如果您要更改密碼/鍵每次加密時,使用靜態零字節IV將有所保障。如果您重複使用密碼/密鑰一次,您將遇到兩次密碼(多次密碼)問題,其中僅觀察密文的攻擊者可能通過查看它們來推斷明文(nice example)。

如果您不能保證一次性使用密碼/密鑰,那麼您每次加密時都必須使用新的IV。沒有更多new IvParameterSpec(new byte[16]),但類似

SecureRandom r = new SecureRandom(); 
byte[] iv = new byte[16]; 
r.nextBytes(iv); 
Arrays.fill(iv, 12, 16, (byte)0); // zero out the counter part