我有一个 JavaScript 加密算法,我正在尝试将其转换为 Python。我尝试研究算法,虽然它不是太复杂,但我无法完全理解并将其转换为 Python 代码。JavaScript代码是
var grecaptcha = []; enc = function (a) { var keyBytes = CryptoJS.PBKDF2('lrvq/wyDf6tqhxvg8NuIDQ==', 'Ivan Medvedev', { keySize: 48 / 4, iterations: 1000 }); // take first 32 bytes as key (like in C# code) var key = new CryptoJS.lib.WordArray.init(keyBytes.words, 32); // skip first 32 bytes and take next 16 bytes as IV var iv = new CryptoJS.lib.WordArray.init(keyBytes.words.splice(32 / 4), 16); // use the same encoding as in C# code, to convert string into bytes var data = CryptoJS.enc.Utf16LE.parse(a); var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv }); $("#capBBC").val(encrypted.toString()); }
我能够编写的 Python 代码是
from Crypto.Protocol.KDF import PBKDF2 from Crypto.Cipher import AES from Crypto.Util.Padding import pad def enc(a): key = PBKDF2("lrvq/wyDf6tqhxvg8NuIDQ==", "Ivan Medvedev", dkLen=48, count=1000) iv = key[32:] data = a.encode('utf-16le') cipher = AES.new(key, AES.MODE_CBC, iv) encrypted = cipher.encrypt(pad(data, AES.block_size)) return encrypted.hex() print(enc("Cat"))
此代码引发以下异常
Traceback (most recent call last): File "C:\Users\Farhan Ahmed\Desktop\code\Python\Kiara Snickers\del.py", line 16, in <module> print(enc("Cat")) File "C:\Users\Farhan Ahmed\Desktop\code\Python\Kiara Snickers\del.py", line 11, in enc cipher = AES.new(key, AES.MODE_CBC, iv) File "C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\AES.py", line 232, in new return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) File "C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\__init__.py", line 79, in _create_cipher return modes[mode](factory, **kwargs) File "C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 274, in _create_cbc_cipher cipher_state = factory._create_base_cipher(kwargs) File "C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\AES.py", line 93, in _create_base_cipher raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) ValueError: Incorrect AES key length (48 bytes)
我不知道 dkLen 的价值应该是多少 提前感谢您的帮助。
在 CryptoJS 代码中,PBKDF2 返回的数据的前 32 个字节用作密钥,但在 Python 代码中是整个数据。 这是 48 字节大,与有效的 AES 密钥不对应,因此导致错误Incorrect AES key length (48 bytes)。 此外,CryptoJS 代码中的密文返回的是 Base64 编码,而不是十六进制编码。
两者的可能解决方法是:
from Crypto.Protocol.KDF import PBKDF2 from Crypto.Cipher import AES from Crypto.Util.Padding import pad import base64 def enc(a): keyIv = PBKDF2("lrvq/wyDf6tqhxvg8NuIDQ==", "Ivan Medvedev", dkLen=48, count=1000) key = keyIv[:32] iv = keyIv[32:] data = a.encode('utf-16le') cipher = AES.new(key, AES.MODE_CBC, iv) encrypted = cipher.encrypt(pad(data, AES.block_size)) return base64.b64encode(encrypted).decode('utf-8') print(enc("Cat")) # CZ/1nUYEjhw4cFj08Yt1EQ==
它返回对应于 CryptoJS 代码的密文:
enc = function (a) { var keyBytes = CryptoJS.PBKDF2('lrvq/wyDf6tqhxvg8NuIDQ==', 'Ivan Medvedev', { keySize: 48 / 4, iterations: 1000 }); // take first 32 bytes as key (like in C# code) var key = new CryptoJS.lib.WordArray.init(keyBytes.words, 32); // skip first 32 bytes and take next 16 bytes as IV var iv = new CryptoJS.lib.WordArray.init(keyBytes.words.splice(32 / 4), 16); // use the same encoding as in C# code, to convert string into bytes var data = CryptoJS.enc.Utf16LE.parse(a); var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv }); console.log(encrypted.toString()); } enc("Cat") <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>