2013-01-02 138 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"); 
}