英文:
Convert Javascript encryption Algorithm to Python
问题
I have a JavaScript Encryption Algorithm, which I am trying to convert into Python. I tried studying the algorithm, though it is not too much complex but I am unable to fully understand and convert it to the Python code. The JavaScript code is
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());
}
The Python code that I was able to write is
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"))
This code raises the following exception
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)
I do not know what should be the value of dkLen. Thanks for any help in advance.
英文:
I have a JavaScript Encryption Algorithm, which I am trying to convert into Python. I tried studying the algorithm, though it is not too much complex but I am unable to fully understand and convert it to the Python code. The JavaScript code is
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());
}
The Python code that I was able to write is
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"))
This code raise the following exception
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)
I do not know what should be value of dkLen
Thanks for any help in advance.
答案1
得分: 1
在CryptoJS代码中,PBKDF2返回的数据的前32个字节被用作密钥,但在Python代码中使用了整个数据。这个数据总共有48个字节,这不对应于有效的AES密钥,因此导致错误"错误的AES密钥长度(48字节)"。此外,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代码相对应的密文。
英文:
In the CryptoJS code the first 32 bytes of the data returned by PBKDF2 are used as key, but in the Python code the entire data.
This is 48 bytes large, which does not correspond to a valid AES key and thus causes the error Incorrect AES key length (48 bytes).
Also, the ciphertext in the CryptoJS code is returned Base64 encoded and not hex encoded.
A possible fix for both is:
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==
which returns a ciphertext corresponding to that of the CryptoJS code:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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")
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<!-- end snippet -->
答案2
得分: 0
在你的js代码中,keySize: 48 / 4
,所以我建议在你的python代码中将其设为12。
更新:
keyBytes = PBKDF2(password, salt, dkLen=48, count=1000)
key = keyBytes[:32]
iv = keyBytes[32:48]
英文:
keySize: 48 / 4
in your js code, so I suggest that it is 12 for your python code
upd:
keyBytes = PBKDF2(password, salt, dkLen=48, count=1000)
key = keyBytes[:32]
iv = keyBytes[32:48]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论