2012-06-16 54 views
3

我想加密和解密一些簡單的文本。但由於某種原因,我收到了一個奇怪的錯誤:javax.crypto.BadPaddingException。爲什麼JCE會生成未正確填充的字節?AES/CBC/PKCS5Padding問題

我有以下代碼:

import javax.crypto.Cipher; 
import javax.crypto.KeyGenerator; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.IvParameterSpec; 
import java.security.SecureRandom; 

public class SimplestTest { 
    public static void main(String[] args) throws Exception { 
     SecureRandom rnd = new SecureRandom(); 

     String text = "Hello, my dear! ... " + System.getProperty("user.home"); 
     byte[] textData = text.getBytes(); 

     IvParameterSpec iv = new IvParameterSpec(rnd.generateSeed(16)); 

     KeyGenerator generator = KeyGenerator.getInstance("AES"); 
     generator.init(128); 
     SecretKey k = generator.generateKey(); 

     Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     c.init(Cipher.ENCRYPT_MODE, k, iv); 
     c.update(textData); 
     byte[] data = c.doFinal(); 

     System.out.println("E: " + data.length); 

     c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     c.init(Cipher.DECRYPT_MODE, k, iv); 
     c.update(data); 

     System.out.println("R: " + c.doFinal().length); 
    } 

} 

但由於某種原因,這是行不通的。它失敗,這個例外:

E: 16 
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded 
     at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
     at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
     at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) 
     at javax.crypto.Cipher.doFinal(DashoA13*..) 
     at SimplestTest.main(SimplestTest.java:31) 

怎麼回事?數據大小爲16個字節,但仍「未正確填充」?

回答

4

Cipher.update也返回一個字節[]。因此,當您解密時,您缺少部分加密數據。更新最後一節,內容如下:

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
c.init(Cipher.ENCRYPT_MODE, k, iv); 
byte[] someData = c.update(textData); 
byte[] moreData = c.doFinal(); 

System.out.println("E: " + (someData.length + moreData.length)); 

c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
c.init(Cipher.DECRYPT_MODE, k, iv); 
byte[] someDecrypted = c.update(someData); 
byte[] moreDecrypted = c.doFinal(moreData); 

System.out.println("R: " + (someDecrypted.length + moreDecrypted.length)); 
+0

非常感謝。現在一切工作正常。 –

4

你可以放棄對update呼叫而直接傳遞byte[]數據doFinal進行加密或一步到位解密的操作。