2010-07-05 6 views
-1

Это код для шифрования и дешифрования строки в java с использованием алгоритма AES. Его бросание исключает блокировку исключения при расшифровке. Я знаю, что это происходит потому, что длина входной строки для метода дешифрования не совпадает с заполнением. У меня нет идеи, как это решить. Я новый bie для расшифровки шифрования. Plz помочь мне ....Исключение в алгоритме дешифрования AES в java

StackTrace:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher 
    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 test.AES.AESdecryptalgo(AES.java:76) 
    at test.AES.main(AES.java:95) 

Код:

package test; 
import javax.crypto.*; 
import javax.crypto.spec.*; 
import java.security.*; 

public class AES 
{ 
    public byte[] encrypted; 
    public byte[] original; 

    public String originalString; 
    Cipher cipher; 
    SecretKeySpec skeySpec; 
    IvParameterSpec spec; 
    byte [] iv; 
    /*public static String asHex (byte buf[]) 
    { 
    StringBuffer strbuf = new StringBuffer(buf.length * 2); 
    int i; 
    for (i = 0; i < buf.length; i++) { 
    if (((int) buf[i] & 0xff) < 0x10) 
    strbuf.append("0"); 
    strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 
    } 
    return strbuf.toString(); 
}*/ 
    public AES() 
    { 
     try 
     { 
      KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
      kgen.init(128); 
      SecretKey skey = kgen.generateKey(); 
      byte[] raw = skey.getEncoded(); 
      skeySpec = new SecretKeySpec(raw, "AES"); 
      cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

     } 
     catch(Exception ex) 
     {ex.printStackTrace();} 
    } 
public String AESencryptalgo(byte[] text) 
{ 
    String newtext=""; 
    try 
    { 
     // byte[] raw = skey.getEncoded(); 
     //SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
      AlgorithmParameters param = cipher.getParameters(); 
      IvParameterSpec ivspec=param.getParameterSpec(IvParameterSpec.class); 
      iv=ivspec.getIV(); 
      spec=new IvParameterSpec(iv); 
     //AlgorithmParameters params = cipher.getParameters(); 
     //iv = params.getParameterSpec(IvParameterSpec.class).getIV(); 
     encrypted = cipher.doFinal(text); 

    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 
     newtext=new String(encrypted); 
     //System.out.println("ENCRYPTED "+newtext); 
     return newtext; 
    } 
} 
public String AESdecryptalgo(byte[] text) 
{ 
    try 
    { 

     cipher.init(Cipher.DECRYPT_MODE, skeySpec,spec); 
     original = cipher.doFinal(text); //Exception occurs here 
     originalString = new String(original); 

    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 

     return originalString; 
    } 
} 
public static void main(String[] args) 
{ 
    AES a=new AES(); 
    String encrypt=a.AESencryptalgo("hello".getBytes()); 
    System.out.println(encrypt); 
    String decrypt=a.AESdecryptalgo(encrypt.getBytes()); 
    System.out.println(decrypt); 
} 

} `

+4

repost ... тем же пользователем !: http://stackoverflow.com/questions/3180878/exception-in-aes-decryption-algorithm-in-java –

+2

@GregS - На самом деле это другое исключение, потому что он недостаточно внимательно следит за примером, представленным по другому вопросу. – erickson

+1

@erickson: Я уверен, что это тот же код. И никто не бросает никаких исключений на мою машину. Конечно, его пример не вызывает функцию, о которой он говорит, что это исключение. –

ответ

4

Вы должны предоставить вектор инициализации при использовании режима CBC.

При шифровании, пусть провайдер выбрать IV для вас:

… 
cipher.init(Cipher.ENCRYPT_MODE, key); 
AlgorithmParameters params = cipher.getParameters(); 
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); 
… 

Позже, при расшифровке, используйте же IV для инициализации шифра:

… 
IvParameterSpec spec = new IvParameterSpec(iv); 
cipher.init(Cipher.DECRYPT_MODE, key, spec); 
… 
+0

Я сделал это изменение ... но затем он выбрасывает исключение нулевого указателя в byte [] iv = params.getParameterSpec (IvParameterSpec.class). getIV(); – sparkle

+0

@ user372066 - Пожалуйста, замените код в своем вопросе текущей версией. – erickson

+0

Я заменил код – sparkle

1

Вы должны изменить AESencryptalgo для возврата byte[], а не String. Вот где начинается беда:

newtext = new String(encrypted); 
// System.out.println("ENCRYPTED "+newtext); 
return newtext; 

После изменения типа возвращаемого методом, вы должны сделать следующее изменение:

//newtext = new String(encrypted); 
// System.out.println("ENCRYPTED "+newtext); 
//return newtext; 
return encrypted; 

Проблема заключается в том, что String последовательность символов , тогда как зашифрованный текст представляет собой последовательность из байтов (для хорошей сводки этой разницы см. The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)).

При попытке построить String из массива байтов, Java делает все возможное, чтобы преобразовать эти байты в символов, используя набор символов по умолчанию в системе. К сожалению, это сопоставление не всегда работает успешно (обычно, когда зашифрованные байты выходят за пределы набора символов ASCII). Вы только заметите проблему, когда придет время до decrypt ваш новый String (который не сможет правильно преобразовать последовательность символов назад в исходную последовательность байт).

Смежные вопросы