这是使用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);
}
}`
答案 0 :(得分:2)
问题是你的构造函数实际上不是构造函数,所以skey
,cipher
和其他私有成员永远不会被初始化。
构造函数的定义没有返回类型,因此您需要将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");