AES ECB 模式在使用不同语言时给出不同的结果

AES ECB Mode giving different results when using different languages

我正在尝试使用 ECB 模式将 AES 加密字符串从 python 脚本传递到 nodejs 脚本。使用的代码是:

首先,我使用 pycryptodome 将字符串加密为 AES

from Crypto.Cipher import AES
key = b'ipu9TUv54yv]isFMh5@;t.5w34E2Ry@{'
cipher = AES.new(key, AES.MODE_ECB)
print(cipher.encrypt(b"foobar          "))

This gives me the string \xb0\x07\x93\xf3\x02\xd0\x87\xa4\xaek\x1bS\xccg\xa4H.

但是,当我尝试使用 Javascript 反转效果时:

var crypto = require('crypto')
let key = Buffer.from('ipu9TUv54yv]isFMh5@;t.5w34E2Ry@{');
let decipher = crypto.createDecipheriv("aes-256-ecb", key, '');
let result = decipher.update(Buffer.from('\xb0\x07\x93\xf3\x02\xd0\x87\xa4\xaek\x1bS\xccg\xa4H'));
console.log(result.toString())

It gives me a completely different result from the original text: �k��gR�O

是否有我遗漏的东西正在改变它的解密方式?

有两个核心问题:

在节点端,您将 Python 的输出视为 UTF-8 字符串。 Node 会将其视为 UTF-8 字符串,组成 Buffer 的结果字节将是错误的。把它转储出来,你会看到它是一个 25 字节的缓冲区,而不是你想要的。

一旦你解决了这个问题,你就会发现第二个问题。加密库需要填充字节,即使唯一的块恰好是块大小。要解决此问题,请始终向明文添加填充。

因此,加密更改为:

from Crypto.Cipher import AES

key = b'ipu9TUv54yv]isFMh5@;t.5w34E2Ry@{'
cipher = AES.new(key, AES.MODE_ECB)
# Don't need to ensure the plain text is exactly block-size anymore
data = b'foobar'
# Pad it, regardless of it's size
length = 16 - (len(data) % 16)
data += bytes([length]) * length

# And encode the encrypted text.  Using hex here, it's easy, though
# often base64 is used
print(cipher.encrypt(data).hex())

并在 Node 中解码:

var crypto = require('crypto')
let key = Buffer.from('ipu9TUv54yv]isFMh5@;t.5w34E2Ry@{');
let decipher = crypto.createDecipheriv("aes-256-ecb", key, '');
// Using the hex encoding, let Buffer decode it
let result = decipher.update(Buffer.from('bf8242c6046ad5cb47e733dca4d487f1', 'hex'));
// Make sure to give decipher a chance to operate on the final block
result += decipher.final();
console.log(result.toString())

这会按预期输出 foobar