简体   繁体   English

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

[英]javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes

I have an ArrayList which contains some objects.我有一个包含一些对象的 ArrayList。 Object is a container for login/pass.对象是登录/通行证的容器。
I try to decode them because i have to serialize them into local file for recreation after another launch.我尝试对它们进行解码,因为我必须将它们序列化到本地文件中,以便在再次启动后重新创建。
Problem is during encryption I recieve问题是在我收到的加密期间

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)

And I completely don't understand why.我完全不明白为什么。 In my opinion Base64 should deal with this.我认为 Base64 应该处理这个问题。 But maybe I don't understand properly its meaning.但也许我没有正确理解它的含义。
I use to encrypt/deccode我用来加密/解码

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 block size is always 128bit, it must receive input in multiples of this number. AES 块大小始终为 128 位,它必须以该数字的倍数接收输入。

Smaller input must be padded to 16 bytes, and the type of padding specified to the algorithm.较小的输入必须填充到 16 个字节,并为算法指定填充类型。

Using "AES/CBC/PKCS5Padding" will do the trick.使用“AES/CBC/PKCS5Padding”可以解决问题。

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

If you use NoPadding, then you must implement your own padding for encryption, and make sure to remove it from the resulting string in decryption.如果您使用 NoPadding,那么您必须实现自己的加密填充,并确保在解密时将其从结果字符串中删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 javax.crypto.IllegalBlockSizeException:输入长度不是8个字节的倍数 - javax.crypto.IllegalBlockSizeException: Input length not multiple of 8 bytes 不断收到 javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是 16 的倍数 - Keep getting javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是16的倍数 - javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher javax.crypto.IllegalBlockSizeException:使用tcp中的填充密码解密时,输入长度必须为16的倍数 - javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher in tcp 获取javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是16的倍数吗? - Getting javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher? javax.servlet.ServletException:javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是16的倍数 - javax.servlet.ServletException: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher 收到javax.crypto.IllegalBlockSizeException的错误:使用填充密码解密时,输入长度必须是8的倍数 - getting error of javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher Java加密:Java加密:javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是8的倍数 - Java Encryption: Java Encription: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher EncryptionException:javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是8的倍数 - EncryptionException: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher 解密错误:javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是8的倍数 - error on Decryption: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM