返回

JavaScript CryptoAES 与 Python CryptoAES 加密结果为何不同?

javascript

JavaScript CryptoAES 和 Python CryptoAES 加密差异

问题

将 JavaScript 中的 CryptoAES 函数移植到 Python 中时,两个函数产生的加密结果不同。

原因

加密函数的实现中存在以下差异:

  • JavaScript 函数使用 CryptoJS 库进行加密,而 Python 函数使用 scryptPyCryptodome 库。
  • 密钥派生函数: JavaScript 函数使用 UTF-8 编码密钥和 IV,而 Python 函数使用 scrypt 算法从连接后的密钥和 IV 派生密钥。

解决方案

为解决差异,请对 Python 函数进行以下修改:

  1. 使用 UTF-8 编码密钥和 IV:

  2. 使用 CryptoJS 兼容的填充:

  3. 确保密钥和 IV 的长度与 CryptoJS 相同:

修改后的 Python 函数

以下是修改后的 Python 函数:

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def CryptoAES(input_string, key, iv, additional_data, tag):
    # Replacing characters 'Ñ' with 'N' and '%' with 'A' in the key
    key = key.replace('Ñ', 'N').replace('%', 'A')

    # Concatenating key, iv, additionalData, and tag
    concatenated_key = key[:7] + iv + additional_data + tag
    concatenated_iv = iv + additional_data + key[1:5] + additional_data + tag

    # Using UTF-8 encoding for key and iv
    parsed_key = Crypto.Util.Padding.pad(concatenated_key, AES.block_size)
    parsed_iv = Crypto.Util.Padding.pad(concatenated_iv, AES.block_size)

    # Encrypting the string using AES encryption in CBC mode with PKCS7 padding
    cipher = AES.new(parsed_key, AES.MODE_CBC, iv=parsed_iv)
    padded_data = pad(input_string.encode(), AES.block_size)
    encrypted_data = cipher.encrypt(padded_data)

    # Using CryptoJS compatible padding
    def CryptoJS_compatible_padding(data):
        length = len(data)
        padding_length = AES.block_size - (length % AES.block_size)
        return data + bytes([padding_length] * padding_length)

    cipher.encrypt(CryptoJS_compatible_padding(padded_data))

    # Returning the encrypted string
    return base64.b64encode(encrypted_data).decode()

结论

通过这些修改,你的 Python 函数将产生与 CryptoJS 函数相同的加密结果。

常见问题解答

1. 为什么使用 CryptoJS 兼容的填充?

CryptoJS 使用 CBC 填充,而 Python 函数使用 PKCS7 填充。为了与 CryptoJS 兼容,请使用 CryptoJS 兼容的填充。

2. 如何确保密钥和 IV 的长度与 CryptoJS 相同?

JavaScript 函数的密钥和 IV 长度为 128 位,而 Python 函数使用 scrypt 算法派生 128 位的密钥和 IV。确保 Python 函数中使用的密钥和 IV 的长度与 JavaScript 函数中相同。

3. 可以使用其他加密库吗?

是的,你可以使用其他加密库,但请确保它们的实现与 CryptoJS 兼容。

4. 如何在不同的语言中移植加密函数?

移植加密函数时,请注意不同语言中的加密库和实现的差异。确保在目标语言中实现与源语言中相同的算法和参数。

5. 如何避免加密结果的差异?

为了避免加密结果的差异,请确保在移植加密函数时遵循以下最佳实践:

  • 仔细检查算法和参数。
  • 使用相同的密钥和 IV 派生函数。
  • 使用相同的填充方案。
  • 测试加密函数以验证结果是否一致。