Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javax.crypto.IllegalBlockSizeException:输入长度不是16字节的倍数_Java_Exception_Aes_Decode_Encode - Fatal编程技术网

javax.crypto.IllegalBlockSizeException:输入长度不是16字节的倍数

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)

我有一个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;
    }
}
公共类移动
{
私有静态移动实例;
字符串键=“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”的内容。为什么要加密/解密密码而不是哈希?因为我将密码保存在文件中,并在启动应用程序时加载密码。