且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用md5消息摘要和DESede/CBC/PKCS5Padding将3DES加密的Java代码转换为python

更新时间:2023-11-23 21:42:04

两个代码之间有很多区别:

There are a lot of differences between both codes:

  • 在Java代码中,密钥是通过将16个字节的MD5散列与同一散列的前8个字节连接而生成的.在Python代码中,密钥生成似乎根本不起作用(从 {:< 24} 更改为 [:24] 并不能真正使它变得更好).最后的第二个更改 digested_pa​​sskey [:24] digested_pa​​sskey 相同,并且可以正常工作,因为 PyCryptodome 会根据2自动将密钥扩展到24个字节键的三重DES.
  • 在Python代码中,使用了两个库: pyDes PyCryptodome .这里只应使用一个库.关于 PyCryptodome ,使用AES.实际上,与Triple DES相比,AES是一种更快/更现代的算法,但它与Java代码的区别仅在于此.
  • Python代码还实现了填充,这是不必要的,因为 PyCryptodome (与传统的 PyCrypto 相比)支持填充.除此之外,填充是错误地实现的,因为它使用的块大小为16个字节,但是Triple DES的块大小为8个字节.
  • 在Java代码中,IV的矢量为0,在Python代码中,随机的IV(实际上是正确的,但与Java代码不同).
  • 在Java代码IV和密文中未连接在一起,在Python代码中将它们连接在一起(实际上是正确的,但与Java代码不同).
  • In the Java code the key is generated by concatenating the 16 bytes MD5 hash with the first 8 bytes of the same hash. In the Python code, key generation does not seem to work at all (changing from {: <24} to [:24] does not really make it better). The 2nd change finally, digested_passkey[:24], is identical to digested_passkey and works because PyCryptodome automatically extends the key to 24 bytes according to 2-key Triple DES.
  • In the Python code, two libraries are used: pyDes and PyCryptodome. Only one library should be applied here. Regarding PyCryptodome AES is used. Actually AES is the faster/modern algorithm compared to Triple DES, but it just differs from that of the Java code.
  • The Python code also implements padding, which is not necessary, because PyCryptodome (in contrast to the legacy PyCrypto) supports padding. Apart from that the padding is wrongly implemented because it uses a block size of 16 bytes, but Triple DES has a block size of 8 bytes.
  • In the Java code a 0 vector is taken for the IV, in the Python code a random IV (which is actually correct, but just differs from the Java code).
  • In the Java code IV and ciphertext are not concatenated, in the Python code they are concatenated (which is actually correct, but just differs from the Java code).

此外,使用的算法是不安全的(MD5)或过时/慢速的(Triple DES),如注释中已经提到的那样.同样,IV的0向量是完全不安全的.

Apart from that, the algorithms used are insecure (MD5) or outdated/slow (Triple DES), as already mentioned in the comment. Also a 0-vector as IV is completely insecure.

import base64
#from Crypto.Cipher import AES
from Crypto.Cipher import DES3
from Crypto.Util.Padding import pad
#import pyDes
#from Crypto import Random
import hashlib


def encrypt(message, passkey):
    
    #hash_object = hashlib.md5(passkey.encode("utf-8"))                       
    hash_object = hashlib.md5(passkey) 
    digested_passkey = hash_object.digest()
    print(digested_passkey)

    #key24 = "[:24]".format(digested_passkey) 
    key24 = digested_passkey + digested_passkey[0:8]        # Derive key as in Java
    
    #des = pyDes.des(key24);                                # Remove pyDes
    
    #message = message.encode('utf-8') 
    #message = message + (16 - len(message) % 16) * chr(16 - len(message) % 16) 
    message = pad(message, 8)                               # Use padding from PyCryptodome       
    
    #iv = Random.new().read(AES.block_size)                 # For Java code compliance: Use 0-IV
    iv = bytes.fromhex('0000000000000000')

    #cipher = AES.new(des, AES.MODE_CBC, iv)                # For Java code compliance: Use TripleDES
    cipher = DES3.new(key24, DES3.MODE_CBC, iv)
    
    #return base64.b64encode(iv + cipher.encrypt(message))  # For Java code compliance: Don't concatenate IV and ciphertext
    return base64.b64encode(cipher.encrypt(message)) 

#print(encrypt('aug@2019', 'Lgp!kdao2020'))                 # Better: Pass binary data
print(encrypt(b'aug@2019', b'Lgp!kdao2020'))

以Java代码( 7B0aNUwOU1ECqKqnIZs6mQ == )给出结果.

which gives the result form the Java code (7B0aNUwOU1ECqKqnIZs6mQ==).