AES算法中的Null PointerException

时间:2010-07-06 04:04:27

标签: java

这是使用AES算法在java中加密和解密字符串的代码。

堆栈跟踪:

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

}`

1 个答案:

答案 0 :(得分:2)

问题是你的构造函数实际上不是构造函数,所以skeycipher和其他私有成员永远不会被初始化。

构造函数的定义没有返回类型,因此您需要将public void AES()更改为public AES


好的,显然你已经解决了这个问题。接下来是cipher.init不接受SecretKey,它需要SecretKeySpec。在this example I found工作,您需要以下内容:

byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

...然后,您可以将skeySpec传递给skey cipher.init的{​​{1}}。


从那时起,我想,除非我指责错误,否则你的问题就出在这一行:

 iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();

如果您确认cipher不为空,则此行上可能引发NullPointerException的地点位于getParameters()来电之后或getParameterSpec()之后。您可以通过将其拆分为多行并检查堆栈跟踪(应该查看堆栈跟踪并确定实际抛出异常的位置)来轻松确定这些调用中的哪一个引发异常)。

如果我不得不下注,我猜我cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");无效。我怀疑如果你有

这会好起来的
cipher = Cipher.getInstance("AES");