使用md5消息摘要和DESede/CBC/PKCS5Padding将3DES加密的Java代码转换为python [英] Converting java code for 3DES Encryption with md5 message digest and DESede/CBC/PKCS5Padding to python

查看:69
本文介绍了使用md5消息摘要和DESede/CBC/PKCS5Padding将3DES加密的Java代码转换为python的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个有效的Java代码,它使用3DES加密对密码进行加密-

I have this working java code which encrypts the passphrase with 3DES encryption-

import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Main{

    public static void main(String[] args) throws Exception {
        String text = "aug@2019";
        String codedtext = new Main().encrypt(text);
        System.out.println(codedtext);
    }

    public String encrypt(String message) throws Exception {
        final MessageDigest md = MessageDigest.getInstance("md5");
        final byte[] digestOfPassword = md.digest("Lgp!kdao2020"
                .getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0, k = 16; j < 8;) {
            keyBytes[k++] = keyBytes[j++];
        }

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final byte[] plainTextBytes = message.getBytes("utf-8");
        final byte[] cipherText = cipher.doFinal(plainTextBytes);
        final String encodedCipherText = new String(java.util.Base64.getMimeEncoder().encode(cipherText),
                         "UTF-8");
        return encodedCipherText;
    }

}

我想在Python中使用相同的加密,因此从两个代码生成的加密都是相同的,这就是我的python代码

I wanted to have the same encryption in Python, so the encryption generated from both the codes are same, this is my python code

import base64
from Crypto.Cipher import AES
import pyDes
from Crypto import Random
import hashlib


def encrypt(message, passkey):
    hash_object = hashlib.md5(passkey.encode("utf-8"))
    digested_passkey = hash_object.digest()
    print(digested_passkey)
    key24 = digested_passkey[:24]
    des = pyDes.des(key24);
    message = message.encode('utf-8')
    message = message + (16 - len(message) % 16) * chr(16 - len(message) % 16)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(des, AES.MODE_CBC, iv)
    return base64.b64encode(iv + cipher.encrypt(message))

print(encrypt('aug@2019', 'Lgp!kdao2020'))

我遇到错误->ValueError:无效的DES密钥大小.密钥必须正好为8个字节长.

I am getting an error -> ValueError: Invalid DES key size. Key must be exactly 8 bytes long.

推荐答案

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

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==).

这篇关于使用md5消息摘要和DESede/CBC/PKCS5Padding将3DES加密的Java代码转换为python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆