2013-01-02 167 views
3

我沒有什麼問題。當我嘗試加密文本,然後解密這段文字,我得到一個錯誤:使用AES CBC加密Java

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

這裏是我的代碼:

import java.io.UnsupportedEncodingException; 
import java.math.BigInteger; 
import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.ShortBufferException; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
/** 
* 
* @author Grzesiek 
*/ 
public class SymmethricCipherCBC { 


    /* Klucz: */ 
    private byte[] keyBytes = new byte[] { 
      0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 
      0x00,0x01,0x02,0x03,0x04,0x05 
     }; 

    /* Wektor inicjalizacyjny: */ 
    private byte[] ivBytes = new byte[] { 
      0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 
      0x00,0x01,0x02,0x03,0x04,0x05 
     }; 

    private Cipher cipher; 
    private SecretKeySpec keySpec; 
    private IvParameterSpec ivSpec; 



    public SymmethricCipherCBC() throws NoSuchAlgorithmException, NoSuchPaddingException{ 
     cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Utworzenie obiektu dla operacji szyfrowania/deszyfrowania algorytmem AES w trybie CBC. 
     keySpec = new SecretKeySpec(keyBytes, "AES"); // Utworzenie obiektu klucza dla algorytmu AES z tablicy bajtow 
     ivSpec = new IvParameterSpec(ivBytes); // // Utworzenie obiektu dla wektora inicjalizacyjnego 
    } 


    public String encryptText(String plainText) throws NoSuchAlgorithmException, 
                InvalidKeyException, 
                NoSuchPaddingException, 
                InvalidAlgorithmParameterException, 
                ShortBufferException, 
                IllegalBlockSizeException, 
                BadPaddingException, 
                UnsupportedEncodingException{ 

     int cipherTextLength; 
     byte[] cipherText; // Bufor dla szyfrogramu 

     byte[] plainTextBytes = plainText.getBytes(); // Reprezentacja tekstu jawnego w bajtach 

     cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); //Inicjalizacja obiektu dla operacji szyfrowania z kluczem okreslonym przez keySpec: 

     cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)]; //Utworzenie buforu dla szyfrogramu 

     cipherTextLength = cipher.update(plainTextBytes, 0, plainTextBytes.length, cipherText, 0); // Szyfrowanie tekstu jawnego 

     cipherTextLength += cipher.doFinal(cipherText, cipherTextLength); //Zakonczenie szyfrowania 

     return new BigInteger(1, cipherText).toString(16); // zapisanie 16 

    } 


    public String decryptText(String ciptherTextString) throws InvalidKeyException, InvalidAlgorithmParameterException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ 

     byte[] cipherTextBytes = ciptherTextString.getBytes(); 

     cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); //Inicjalizacja obiektu cipher dla odszyfrowywania z kluczem okreslonym przez keySpec 

     byte[] plainTextBytes = new byte[cipher.getOutputSize(cipherTextBytes.length)]; // Utworzenie wyzerowanej tablicy 

     int plainTextLength = cipher.update(cipherTextBytes, 0, cipherTextBytes.length, plainTextBytes, 0); 
     plainTextLength += cipher.doFinal(plainTextBytes, plainTextLength); 

     return new String(plainTextBytes); //Odtworzona wiadomosc 
    } 
} 

任何想法,我應該怎麼辦?

+0

請提供堆棧跟蹤。這裏 – Doorknob

+0

同樣的問題:http://stackoverflow.com/questions/14109626/javax-crypto-badpaddingexception-unknown-block-type/14109701#14109701 – Henry

+0

你encryptText和decryptText方法有明顯不符,再加上你的encryptText方法使用的編碼每256次加密就會失敗一次提示:前導零在密碼中很重要。 –

回答

0

,據我所知,你正在服用的加密算法的字節數組輸出,並將其轉換爲使用BigInteger的十六進制字符串。那麼解密算法將採用十六進制字符串並將其轉換爲使用十六進制字符串中的ASCII字符的字節表示形式.toString()

這是您的代碼出錯的地方(以及其他地方)。而不是將十六進制字符串輸出「FFFF」轉換成字節數組[0xff, 0xff],它將其變成字節數組[0x46,0x46,0x46,0x46](例如,大寫字母F的ASCII字節表示)。這意味着,不僅轉換中的所有字節都是錯誤的,字節數組的長度將會錯誤(這會導致您在問題中列出的異常)。

相反,您應該從您的加密方法返回byte[],並接受byte[]作爲解密方法中的參數。否則,您應該使用類似Apache Commons Codec的Hex類來可靠地在字節數組和十六進制字符串之間進行轉換。

3

你這樣做是不是有必要更加努力,和你做

cipher.doFinal(cipherText, cipherTextLength); 

的時候我都會把它改寫爲是加密的密文:

public String encryptText(String plainText) throws ... { 
    byte[] plainTextBytes = plainText.getBytes("UTF8"); 
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 
    byte[] encrypted = cipher.doFinal(plainTextBytes); 
    return toHex(encrypted); 
} 

public String decryptText(String cipherTextString) throws ... { 
    byte[] cipherTextBytes = fromHex(cipherTextString); 
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); 
    byte[] plainTextBytes = cipher.doFinal(cipherTextBytes); 
    return new String(plainTextBytes, "UTF8"); 
}