Python AES 解密以不同字符结尾的字符串

1 投票
1 回答
961 浏览
提问于 2025-04-17 06:09

我有一个输入字符串,我用MySQL的AES_ENCRYPT来加密它,然后用Python来解密(不是用MySQL的AES_DECRYPT)。我打印了一些解密后的字符串测试结果:

print decrypt_string
print "%sxxx" % decrypt_string
print len(decrypt_string)
print self.toHex(decrypt_string)

当输入字符串长度为8,也就是“abcdefgh”时,测试输出结果是:

abcdefgh
xxxdefgh
16
0x610x620x630x640x650x660x670x680x80x80x80x80x80x80x80x8

如果输入字符串长度为7,也就是“abcdefg”:

abcdefg                                 
abcdefg                                 xxx
16
0x610x620x630x640x650x660x670x90x90x90x90x90x90x90x90x9

我发现,当输入字符串的长度增加时,最后的字符逐渐减少。为什么会有这样的差异呢?如果我用PHP的AES加密,而不是MySQL的AES_ENCRYPT,最后的字符会是0x00。我使用的是一个第三方的Python AES库

1 个回答

1

你观察到的现象是因为AES是一种分组密码,它只能以128位(也就是16字节)为单位来加密数据。为了加密更大块的数据,通常会使用一种操作模式和填充模式。看起来你的Python解密函数能够解密数据,但没有去掉填充部分,这就导致了你看到的结果。

你使用的是PKCS#5填充,这种填充方式会在数据后面加上一些字节(至少一个),这些字节的值和数量是相同的,这样最终的长度就会是块长度的倍数。

  • 对于你8字节的字符串,需要加上8个字节,每个字节的值都是8。ASCII码中的8是退格符,这在你的终端中会把光标向左移动一次(总共8次),所以就出现了xxx覆盖了abc的情况。
  • 对于你7字节的字符串,需要加上9个字节,每个字节的值都是9。这是水平制表符,这样你的xxx就会出现在右边。

你可以选择找出如何给解密函数提供正确的填充模式(它应该有这样的选项),或者自己去掉填充:检查解密字符串的最后一个字节,把它转换成数字(用它的ASCII值),然后从decrypt_string的末尾去掉那么多字节。你还应该检查这些字节的值是否都相同。
(你应该先做这个,再把输出当作字符串来处理,也就是应用像UTF-8或ASCII这样的编码。)

撰写回答