NodeJS AES 加密 Python 解密

NodeJS AES encrypt Python decrypt

我有一个 nodejs 服务,它对一些需要在 Python 中解密的数据使用 AES 加密。 无论我做什么,我都无法让它发挥作用。 NodeJS 代码:

const algorithm = 'aes-128-ctr';

function encryptScript(data, key) {
    const cipher = crypto.createCipher(algorithm, key);

    let crypted = cipher.update(data, 'utf8', 'hex');
    crypted += cipher.final('hex');

    return crypted;
}

我试过 Python:

counter = Counter.new(128)
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
print cipher.decrypt(enc.decode("hex"))

但它不起作用。

我的第一个问题是 Python 代码不接受长度超过 32 字节的密钥(而 Nodejs 代码接受)。

如果我使用 NodeJS 加密模块,解密工作正常:

function decryptScript(data, key) {
    const decipher = crypto.createDecipher(algorithm, key);
    let dec = decipher.update(data, 'hex', 'utf8');
    dec += decipher.final('utf8');
    return dec;
}

我不知道节点在做什么,但它可能与数据的某些填充有关。

我怎样才能让它发挥作用?

(我更喜欢不需要更改 NodeJS 代码而只需要更改 Python 脚本的解决方案)。

  • CreateCipher uses EVP_BytesToKey to create a key and an IV from a password (what is called a key in the NodeJS-code is actually the password). Here is an implementation of EVP_BytesToKey in Python. The parameters to use are described in the documentation of CreateCipher: MD5, no salt, one iteration. In CTR-mode IV 通常随着每个块从要定义的值开始递增。 CreateCipher 使用 EVP_BytesToKey 确定的 IV 作为起始值。 CreateCipher 的功能因此可以在 Python 中实现如下:

    import hashlib
    from Crypto.Cipher import AES
    from Crypto.Util import Counter
    
    ...
    
    encrypted = '5e99b5190f12143c057f6bdd8625f958682e737c11e138a2f571c050313dbe1008347604c7c7e8bf506a0a'   # Example
    
    # Generate key and iv
    keySize = 16
    ivSize = 16
    digest = hashlib.md5
    salt = b''
    password = b'123456'                                                                                   # Example
    iteration = 1
    keyiv = EVP_BytesToKey(keySize, ivSize, digest, salt, password, iteration)
    key = keyiv[0]
    iv = keyiv[1]
    
    # Define counter
    nbits = 128
    initial_value = int.from_bytes(iv, byteorder = 'big');
    counter = Counter.new(nbits, initial_value = initial_value)
    
    # Decrypt
    cipher = AES.new(key, AES.MODE_CTR, counter = counter)
    decrypted = cipher.decrypt(bytes.fromhex(encrypted))
    print("Decrypted: " + decrypted.decode('utf8'))
    

    密文是使用 NodeJS-code 使用以下输入生成的:

    key = '123456';
    data = 'The quick brown fox jumps over the lazy dog';
    
  • 注意CreateCipher is deprecated and should no longer be used, especially not in combination with the CTR-mode. Instead CreateCipheriv can be used. In CTR-mode, it is important that a key/IV-pair is used only once. Otherwise the security will be lost, see hereCreateCipher 不提供随机化,即相同的密码始终生成相同的密钥和 IV,因此始终生成相同的密钥流。因此,如果多次使用相同的密码,就会失去安全性。另一方面,CreateCipheriv 需要一个密钥和一个随机 IV。这里有一个键可以 多次使用,只要 IV 的随机化确保 key/value-pairs 不重复,参见 .