AES解密的有效结果在一个字节和一个字节上有多少可能不同?

问题描述:

我需要在Java中解密AES加密字节。源数据以2个已知验证字节开始,作为成功解密的指示。由于某些协议原因,数据的长度小于255个字节,并且假如数据已经被加密的人需要填充数据,使用前面提到的相同验证字节作为填充。我用我的可用方法成功解密了数十万条记录。AES解密的有效结果在一个字节和一个字节上有多少可能不同?

现在我得到一些成功(?)解密后的一个和一个字节与解密结果不同的记录。当然,这不是验证字节;-),而是其他一个字节,具有非常特殊的记录意义。总是有相同的字节,始终是相同的,不断的错误值。我只是说,例如根据某些制造商的具体文档,获得0x47,我应该有0x44

就这么简单,根据我的文档和结果,其他结果都是正确的。现在的问题是,我得到的数据制造商声称真的获得0x44而不是我的0x47具有完全相同的输入数据。不同我们有意见......

因为我使用CipherAES/CBC/NoPadding和我的应用程序的调试解密我可以看到调用Cipher.final后,我已经在我的结果数据错误0x47。因为我不觉得我的做法有任何错误,我决定测试替代AES解密器,发现3个不同的实现方式,声称我有完全一样的输入数据完全相同的结果(!):

有是其他AES解密器,但其中大多数不提供对init矢量的支持,因此不提供c直接结果。这就是整个观点,不同的输入会产生不同的输出,根据我的测试,差异总是很大。从来不只是几个字节发生了变化或者其他什么,它总是完全错误的或者完全正确的,除了我看到的一个字节。

因此,如果实施了适当的AES,那么对于相同的AES解密操作,同一个输入是否会产生不同的结果?我不这么认为。

错误的输入可能产生正确结果的可能性是多少,除了一个字节?因为我的或其他输入可能只是错误的,即使它被复制,我没有看到任何区别。

错误的AES实现可能产生接近正确的结果的可能性有多大? Java有多大可能提供了错误的AES实现?我不这么认为。

关于我可以测试什么的任何提示?对我来说,看起来我可能有3个不同的附加实现都证明了我的结果,所以我认为我所做的是正确的,并且由于某些原因,一个特殊字节的差异需要来自其他地方。

谢谢!

在这种情况下,看起来不正确的字节在第一个块中,因此由不正确的IV引起。

扩展上的答案的评论:

的IV与数据的第一个块异或,见CBC mode decryption。在加密时,IV的单字节(或比特)改变将影响所有字节,但是在解密时它仅影响第一块中对应于IV中字节(或比特)不正确的字节(比特)。

另一种常见方法是将IV加入加密数据中,避免必须通过另一个通道/方法共享IV,以确保它是正确的。

这确实指出验证方案很差。更好的方案考虑到所有加密字节,通常是加密数据的HMAC。但是在计算有限的环境中,CRC或甚至校验和可能就足够了。

除了一个字节,错误输入是否可能产生正确结果的可能性有多大?

这可能是非常有可能的,这取决于输入错误:我找到了差异,这是之一,这是不同的初始化向量只有一个字节和差异使得在实际的结果只有一个字节的差异。

初始化向量的区别来自对底层规范的不同理解,它定义了如何正确地构建init向量。数据来自某些需要在数据中包含版本号的设备,并且该规范允许同时在两个不同的地方包含该版本。对于目前有问题的记录,它有两个不同的地方可用,但也有两个不同的值。所以我从第一个地方使用版本号,而另一方使用第二个地方的版本号,并且由于两个值不同,我们得到不同的初始化向量和不同的结果。

WTF ?! :-)

+1

IV与第一块数据联动,请参阅[CBC模式解密](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29)。你不指定加密模式,我假设CBC模式。在加密时,单个字节会影响所有字节,但在解密时它只会影响IV中不正确的字节。 – zaph

在CBC模式下,使用密钥对每个密文块进行解密,然后将该结果与先前的密文块进行XOR,以恢复纯文本。

由于这是一个简单的XOR操作,翻转前面密文中的位将翻转当前纯文本块中的相应位。 (当然,用翻转的位对数据进行解密也会完全破坏前面的纯文本块)。

解密第一个块时没有“前一个”密文块。这就是初始化向量进来的地方。它充当密码文本的第零块,并且如上所述,对IV的改变将导致第一个纯文本块中的比特改变。