我有一个包含一些对象的ArrayList。对象是用于登录/传递的容器。
我尝试对它们进行解码,因为在再次启动后我必须将它们序列化为本地文件以进行娱乐。
问题是我收到加密时
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;
}
}
AES块大小始终为128位,它必须以该数字的倍数接收输入。
较小的输入必须填充为16个字节,并为算法指定填充类型。
使用“ AES / CBC / PKCS5Padding”将达到目的。
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
如果使用NoPadding,则必须实现自己的填充进行加密,并确保从解密结果字符串中删除该填充。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句