Exception in AES decryption algorithm in java

你说的曾经没有我的故事 提交于 2019-11-30 00:04:20

问题


This is the code for encrypting and decrypting a string in java using AES algorithm. Its throwing illegalblocksize exception while decrypting. I know it is occuring because length of input string to the decryption method isn't matching with the padding. I don't have an idea of how to solve this. I am a new bie to the encryption decryption. Plz help me....

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)

Code:

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);
}

}`


回答1:


You have to provide an initialization vector when using CBC mode.

When encrypting, let the provider choose the IV for you:

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

Later, when decrypting, use the same IV to initialize the cipher:

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



回答2:


You must change AESencryptalgo to return byte[] rather than a String. This is where the trouble begins:

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

After changing the return type of the method, you should make the following change:

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

The problem is that a String is a sequence of characters, whereas the encrypted text is a sequence of bytes (for a good summary of this difference, see The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)).

When you try to construct a String from a byte array, Java tries its best to convert those bytes into characters, using the system's default character set. Unfortunately, this mapping doesn't always work successfully (typically when the encrypted bytes fall outside the ASCII character set). You will only ever notice the problem when it comes time to decrypt your new String (which will fail to properly convert the sequence of characters back into the original sequence of bytes).



来源:https://stackoverflow.com/questions/3181535/exception-in-aes-decryption-algorithm-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!