将JavaScript加密算法转换为Python。

huangapple go评论86阅读模式
英文:

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(&#39;lrvq/wyDf6tqhxvg8NuIDQ==&#39;, &#39;Ivan Medvedev&#39;, { 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 });
$(&quot;#capBBC&quot;).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(&quot;lrvq/wyDf6tqhxvg8NuIDQ==&quot;, &quot;Ivan Medvedev&quot;, dkLen=48, count=1000)
    iv = key[32:]
    data = a.encode(&#39;utf-16le&#39;)
    
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(pad(data, AES.block_size))
    
    return encrypted.hex()

print(enc(&quot;Cat&quot;))

This code raise the following exception

Traceback (most recent call last):
  File &quot;C:\Users\Farhan Ahmed\Desktop\code\Python\Kiara Snickers\del.py&quot;, line 16, in &lt;module&gt;
    print(enc(&quot;Cat&quot;))
  File &quot;C:\Users\Farhan Ahmed\Desktop\code\Python\Kiara Snickers\del.py&quot;, line 11, in enc
    cipher = AES.new(key, AES.MODE_CBC, iv)
  File &quot;C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\AES.py&quot;, line 232, in new
    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
  File &quot;C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\__init__.py&quot;, line 79, in _create_cipher
    return modes[mode](factory, **kwargs)
  File &quot;C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\_mode_cbc.py&quot;, line 274, in _create_cbc_cipher
    cipher_state = factory._create_base_cipher(kwargs)
  File &quot;C:\Users\Farhan Ahmed\AppData\Local\Programs\Python\Python310\lib\site-packages\Crypto\Cipher\AES.py&quot;, line 93, in _create_base_cipher
    raise ValueError(&quot;Incorrect AES key length (%d bytes)&quot; % 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(&quot;lrvq/wyDf6tqhxvg8NuIDQ==&quot;, &quot;Ivan Medvedev&quot;, dkLen=48, count=1000)
    key = keyIv[:32]
    iv = keyIv[32:]
    data = a.encode(&#39;utf-16le&#39;)
    
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(pad(data, AES.block_size))
    
    return base64.b64encode(encrypted).decode(&#39;utf-8&#39;)

print(enc(&quot;Cat&quot;)) # 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(&#39;lrvq/wyDf6tqhxvg8NuIDQ==&#39;, &#39;Ivan Medvedev&#39;, { 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(&quot;Cat&quot;)

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js&quot;&gt;&lt;/script&gt;

<!-- 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]

huangapple
  • 本文由 发表于 2023年6月15日 19:28:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76481996.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定