javax.crypto.IllegalBlockSizeException:输入长度不是16字节的倍数
我有一个ArrayList,其中包含一些对象。对象是用于登录/传递的容器javax.crypto.IllegalBlockSizeException:输入长度不是16字节的倍数,java,exception,aes,decode,encode,Java,Exception,Aes,Decode,Encode,我有一个ArrayList,其中包含一些对象。对象是用于登录/传递的容器 我尝试对它们进行解码,因为在另一次发布后,我必须将它们序列化到本地文件中以供娱乐。 问题是在我接收加密的过程中 javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1039)
我尝试对它们进行解码,因为在另一次发布后,我必须将它们序列化到本地文件中以供娱乐。
问题是在我接收加密的过程中
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1039)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:983)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
我完全不明白为什么。我认为Base64应该处理这个问题。但也许我没有正确理解它的意思。我使用加密/解密代码
public class Move
{
private static Move instance;
String key = "pT5IkWNR90gJo5YM";
String initVector = "RandomInitVector";
Cipher cipher;
private Move()
{
// try
// {
// cipher = Cipher.getInstance("AES/CBC/NoPadding");
// }
// catch (NoSuchAlgorithmException | NoSuchPaddingException e)
// {
// e.printStackTrace();
// }
}
public void saveData(ArrayList<Account> dataToSave)
{
try
{
FileOutputStream fileOut = new FileOutputStream(Config.SERIAL_FILE);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(encrypt(dataToSave));
out.close();
fileOut.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public ArrayList<Account> loadData()
{
ArrayList<Account> loadedData = new ArrayList<Account>();
File f = new File(Config.SERIAL_FILE);
if (f.exists())
{
try
{
FileInputStream fileIn = new FileInputStream(Config.SERIAL_FILE);
ObjectInputStream in = new ObjectInputStream(fileIn);
loadedData = (ArrayList<Account>) in.readObject();
in.close();
fileIn.close();
}
catch (IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
loadedData = decrypt(loadedData);
}
else
{
loadedData = new ArrayList<Account>();
}
return loadedData;
}
private ArrayList<Account> encrypt(List<Account> decrypted)
{
ArrayList<Account> encrypted = new ArrayList<Account>();
try
{
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
for (int i = 0; i < decrypted.size(); i++)
{
try
{
byte[] login = cipher.doFinal(Base64.getDecoder().decode(decrypted.get(i).getLogin().getBytes()));
encrypted.add(new Account(login.toString(), "pass"));
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
catch (InvalidKeyException | InvalidAlgorithmParameterException | UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException e)
{
e.printStackTrace();
}
return encrypted;
}
private ArrayList<Account> decrypt(List<Account> encrypted)
{
ArrayList<Account> decrypted = new ArrayList<Account>();
try
{
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
for (int i = 0; i < encrypted.size(); i++)
{
byte[] login = cipher.doFinal(Base64.getDecoder().decode(encrypted.get(i).getLogin()));
decrypted.add(new Account(new String(login), "pass"));
}
}
catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException e)
{
e.printStackTrace();
}
return decrypted;
}
public static Move getMove()
{
if (instance == null)
{
instance = new Move();
}
return instance;
}
}
公共类移动
{
私有静态移动实例;
字符串键=“pT5IkWNR90gJo5YM”;
字符串initVector=“RandomInitVector”;
密码;
私人搬家()
{
//试一试
// {
//cipher=cipher.getInstance(“AES/CBC/NoPadding”);
// }
//捕获(NoSuchAlgorithmException | NoSuchPaddingException e)
// {
//e.printStackTrace();
// }
}
public void saveData(ArrayList dataToSave)
{
尝试
{
FileOutputStream fileOut=新的FileOutputStream(Config.SERIAL\u文件);
ObjectOutputStream out=新的ObjectOutputStream(fileOut);
writeObject(加密(dataToSave));
out.close();
fileOut.close();
}
捕获(IOE异常)
{
e、 printStackTrace();
}
}
@抑制警告(“未选中”)
公共ArrayList loadData()
{
ArrayList loadedData=新建ArrayList();
文件f=新文件(Config.SERIAL\u文件);
如果(f.exists())
{
尝试
{
FileInputStream fileIn=新文件inputstream(Config.SERIAL\u文件);
ObjectInputStream in=新的ObjectInputStream(fileIn);
.readObject()中的loadedData=(ArrayList);
in.close();
fileIn.close();
}
捕获(IOException | ClassNotFoundException e)
{
e、 printStackTrace();
}
loadedData=解密(loadedData);
}
其他的
{
loadedData=new ArrayList();
}
返回加载的数据;
}
私有ArrayList加密(列表解密)
{
ArrayList encrypted=新的ArrayList();
尝试
{
IvParameterSpec iv=新的IvParameterSpec(initVector.getBytes(“UTF-8”);
SecretKeySpec skeySpec=新的SecretKeySpec(key.getBytes(“UTF-8”),“AES”);
cipher=cipher.getInstance(“AES/CBC/NoPadding”);
cipher.init(cipher.ENCRYPT_模式,skeySpec,iv);
for(int i=0;i
AES块大小始终为128位,它必须以该数字的倍数接收输入
较小的输入必须填充到16字节,并且填充类型必须指定给算法
使用“AES/CBC/PKCS5Padding”就可以了
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
如果使用NoPadding,则必须实现自己的加密填充,并确保在解密时将其从结果字符串中删除。我是否正确理解填充是某种类型的完成?是的,例如,如果密码为“1234”,AES将预期类似“1234000000000000”的内容。为什么要加密/解密密码而不是哈希?因为我将密码保存在文件中,并在启动应用程序时加载密码。