Java 给定的最终块未正确填充AES256

Java 给定的最终块未正确填充AES256,java,encryption,aes,Java,Encryption,Aes,我有一个密钥,我想用这个密钥解密数据,但给出的最后一个块没有正确填充错误出现 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] encryptedBytes_updates = cipher.update(enc

我有一个密钥,我想用这个密钥解密数据,但给出的最后一个块没有正确填充错误出现

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] encryptedBytes_updates = cipher.update(encryptedBytes);
    String decryptedText = new String(cipher.doFinal(encryptedBytes_updates));
我尝试了一些论坛上的建议,但没有成功


可能有人能帮忙吗?

如果您解码的消息少于16字节,其中一个问题可能是您使用了错误的IV。具体来说,这一行是不正确的:

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[cipher.getBlockSize()]));
您正在从所有0的字节数组创建一个
IvParameterSpec
(因为您刚刚创建了它,但没有用任何数据填充它)。如果在加密时执行相同的操作,这就是加密/解密在本地工作的原因

您需要做的是使用包含服务器发送给您的IV的字节数组创建
IvParameterSpec
。如果服务器没有在单独的字段中向您发送IV,则可能是IV已预先添加或附加到您收到的加密数据中(这是一种相当常见的做法)。我会尝试提取加密数据的第一块(16字节)并将其用作IV。如果这不起作用,请尝试加密数据的最后一块。或者更好的办法是,询问运行服务器或阅读手册的人,以确定从何处获取IV

此外,这看起来也不正确:

byte[] encryptedBytes_updates = cipher.update(encryptedBytes);
String decryptedText = new String(cipher.doFinal(encryptedBytes_updates));
为什么要将
encryptedBytes\u更新
并将其反馈到密码中
update
解密数据,然后尝试使用
doFinal
再次解密。改为这样做:

String decryptedText = new String(cipher.doFinal(encryptedBytes));

如果您解码的消息少于16字节,其中一个问题可能是您使用了错误的IV。具体来说,这一行是不正确的:

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[cipher.getBlockSize()]));
您正在从所有0的字节数组创建一个
IvParameterSpec
(因为您刚刚创建了它,但没有用任何数据填充它)。如果在加密时执行相同的操作,这就是加密/解密在本地工作的原因

您需要做的是使用包含服务器发送给您的IV的字节数组创建
IvParameterSpec
。如果服务器没有在单独的字段中向您发送IV,则可能是IV已预先添加或附加到您收到的加密数据中(这是一种相当常见的做法)。我会尝试提取加密数据的第一块(16字节)并将其用作IV。如果这不起作用,请尝试加密数据的最后一块。或者更好的办法是,询问运行服务器或阅读手册的人,以确定从何处获取IV

此外,这看起来也不正确:

byte[] encryptedBytes_updates = cipher.update(encryptedBytes);
String decryptedText = new String(cipher.doFinal(encryptedBytes_updates));
为什么要将
encryptedBytes\u更新
并将其反馈到密码中
update
解密数据,然后尝试使用
doFinal
再次解密。改为这样做:

String decryptedText = new String(cipher.doFinal(encryptedBytes));


发生这种情况的原因有很多,包括:IV错误、密钥错误、数据损坏。我测试了一个密钥字符串,结果是一样的。我将数据发送到使用openssl的服务器,然后服务器将数据发送回。我尝试在本地对数据进行加密和解密,但对服务器上的数据不起作用。现在我有一个输入长度必须是16的倍数,当使用填充密码错误进行解密时。如果您指定发生异常的行,这将非常有用。是
cipher.update
行还是
cipher.doFianl
行?如果使用
NoPadding
临时解密,则可以查看最后一个块并查看源代码使用的填充。或者,整个块都是垃圾,您的问题在于键或可能是IV。我怀疑您比较键“string”;不要这样做,比较密钥字节。将字符串转换为字节有不同的方法,您需要确保两端使用相同的转换。发生这种情况的原因有很多,包括:IV错误、密钥错误、数据损坏。我测试了一个密钥字符串,结果是相同的。我将数据发送到使用openssl的服务器,然后服务器将数据发送回。我尝试在本地对数据进行加密和解密,但对服务器上的数据不起作用。现在我有一个输入长度必须是16的倍数,当使用填充密码错误进行解密时。如果您指定发生异常的行,这将非常有用。是
cipher.update
行还是
cipher.doFianl
行?如果使用
NoPadding
临时解密,则可以查看最后一个块并查看源代码使用的填充。或者,整个块都是垃圾,您的问题在于键或可能是IV。我怀疑您比较键“string”;不要这样做,比较密钥字节。有不同的方法将字符串转换为字节,您需要确保两端使用相同的转换。由于模式为CBC,不正确的IV只会使第一个块出错。因此,只有当密文的大小为1块时,才会出现填充错误。@zindorsky:是的,我的错误。编辑以反映这一点。尽管如此,由于他的IV代码几乎肯定是不正确的,所以留下了大部分信息。如果服务器根本没有使用IV怎么办?如果没有,那么您使用的是错误的算法模式。CBC总是需要IV操作,如果没有IV,服务器使用的加密模式可能是ECB。你真的需要和运行服务器或阅读手册的人谈谈。试图猜测所有这些东西是行不通的。我认为最后一部分将抛出异常,很可能就是答案。如果解密两次,填充算法很可能失败(对于不同的输入,256次解密中约有255次)。由于模式为CBC,错误的IV只会使第一个块出错。因此,只有当密文的大小为1块时,才会出现填充错误。@zindorsky:是的,我的错误。编辑以反映这一点。尽管如此,由于他的IV代码几乎肯定是不正确的,所以留下了大部分信息。如果服务器根本没有使用IV怎么办?如果没有,那么您使用了错误的算法