在 python3 中将 md5 哈希转换为正确的 3DES 密钥

Converting md5 hash to a proper 3DES key in python3

我有一个用 c# 编写的函数,您可以传递一个 ascii 字符串作为密钥,以及来自数据库的加密字符串并解码数据。

我已经通过编写一个简单的 c# 程序来解码数据来验证代码是否有效。代码片段将密钥字符串转换为字节,并对其进行 MD5 哈希处理。

C# 代码片段,省略了一些将 byteHash 转换为 ascii 字符串以在编译程序中输出的代码

key = "joetest"

byte[] byteHash =  cryptoServiceProvider.ComputeHash(Encoding.ASCII.GetBytes(key));

byteHash = "f2fc0f481787cc4cbb15f7ded4412fe4"

我运行以下命令和Python3得到相同的byteHash

key = "joetest" 
encoded_key = key.encode("ascii")
m = hashlib.md5()
m.update(encoded_key)
hex_key = m.hexdigest()
print(hex_key)

hex_key = "f2fc0f481787cc4cbb15f7ded4412fe4"

我试过将 'hex_key' 编码为二进制。

我的问题是我试图将 hex_key 传递给 2 个不同的 python3 加密程序。 Cryptodome 和 pyDes。两者都告诉我我传递的是无效密钥。

使用byteHash的C#代码如下

tripleDesCryptoServiceProvider.Key = byteHash;

tripleDesCryptoServiceProvider.Mode = CipherMode.ECB;

byte[] byteBuff = Convert.FromBase64String(encryptedString);

string strDecrypted = Encoding.UTF8.GetString(tripleDesCryptoServiceProvider.CreateDecryptor().TransformFinalBlock(byteBuff, 0, byteBuff.Length));

一切正常,当我将加密的字符串传入此函数时,我能够解密数据。

使用 pyDes 我正在使用此代码

from pyDes import *
import base64
import hashlib


my_data = "fK/jw6/25y0="
#my_data is the word 'test' encrypted with the key of 'joetest'

#This code takes the key string and converts it to an MD5 hash
my_key = "joetest"
encoded_key = my_key.encode("ascii")    #Encode the data as binary data
m = hashlib.md5()           
m.update(encoded_key)
hex_key = m.hexdigest()         #Convert the key to an MD5 hash
encoded_hex_key = hex_key.encode()  #Make the MD5 key a binary key  

#Convert the Base64 encoded string to the format that the decoder wants
decoded_data = base64.b64decode(my_data)

k = triple_des(encoded_hex_key, ECB, padmode=PAD_PKCS5)
my_out = k.decrypt(decoded_data)
print("my_out")
print(my_out)
exit()

我得到的错误是:

(3destest) c:des-testdestest>joe3des_test3.py
Traceback (most recent call last):
  File "C:des-testdestest\joe3des_test3.py", line 20, in <module>
    k = triple_des(encoded_hex_key, ECB, padmode=PAD_PKCS5)
  File "c:des-testdestest\lib\site-packages\pyDes.py", line 710, in __init__
    self.setKey(key)
  File "c:des-testdestest\lib\site-packages\pyDes.py", line 719, in setKey
    raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
ValueError: Invalid triple DES key size. Key must be either 16 or 24 bytes long

使用 pyCryptodome,我试过这段代码

from Cryptodome.Cipher import DES3
import base64
import hashlib

# Converts the key string to an MD5 hash
key = "joetest" 
encoded_key = key.encode("ascii")
m = hashlib.md5()
m.update(encoded_key)
hex_key = m.hexdigest()

#Decodes the string to binary digits
encryptedString = base64.b64decode("fK/jw6/25y0=")

#Create the cipher to decrypt the data
cipher = DES3.new(hex_key, DES3.MODE_ECB)
decryptedString = cipher.decrypt(encryptedString)

我收到这个错误

Traceback (most recent call last):
  File "C:des-testdestest\joe3des_test2.py", line 16, in <module>
    cipher = DES3.new(hex_key, DES3.MODE_ECB)
  File "c:des-testdestest\lib\site-packages\Cryptodome\Cipher\DES3.py", line 174, in new
    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
  File "c:des-testdestest\lib\site-packages\Cryptodome\Cipher\__init__.py", line 55, in _create_cipher
    return modes[mode](factory, **kwargs)
  File "c:des-testdestest\lib\site-packages\Cryptodome\Cipher\_mode_ecb.py", line 175, in _create_ecb_cipher
    cipher_state = factory._create_base_cipher(kwargs)
  File "c:des-testdestest\lib\site-packages\Cryptodome\Cipher\DES3.py", line 99, in _create_base_cipher
    key = adjust_key_parity(key_in)
  File "c:des-testdestest\lib\site-packages\Cryptodome\Cipher\DES3.py", line 80, in adjust_key_parity
    raise ValueError("Not a valid TDES key")
ValueError: Not a valid TDES key

我的 python MD5 散列长度为 32 个十六进制字符。假设我的数学是正确的,32 * 4 是 128 位。错误是说它必须是 16 或 24 个字节长。 16 * 8 也是 128 位。所以我传递给它的字节字符串值应该是正确的。我想我遗漏了什么,但似乎无法弄清楚。

2018 年 1 月 2 日更新 根据下面的答案,这是我用来确认这将解密数据库中数据的代码副本。

from pyDes import *
import base64
import hashlib

#my_data is the word 'test' encrypted with the key of 'joetest'
my_data = "fK/jw6/25y0="


#This code takes the key string and converts it to an MD5 hash
my_key = "joetest"
encoded_key = my_key.encode("ascii")
m = hashlib.md5()
m.update(encoded_key)
digest_key = m.digest()

#Convert the Base64 encoded string to the format that the decoder wants
decoded_data = base64.b64decode(my_data)

k = triple_des(digest_key, ECB)
my_out = k.decrypt(decoded_data)
print("my_out")
print(my_out.decode("ascii"))

TripleDES,根据定义,意味着使用 24 字节密钥,例如192 位。接受少于实际重用关键数据的实现。

在 C# 中,具有 128 位密钥的 TripleDES 重复使用前 64 位来创建长度为 192 位的密钥。

考虑到这一点,请尝试改用以下 192 位密钥:

f2fc0f481787cc4cbb15f7ded4412fe4f2fc0f481787cc4c

如果这可行(我希望它会成功),您只需修改代码以将前 64 位复制到末尾。

错误

line 80, in adjust_key_parity raise ValueError("Not a valid TDES key")

来自pyCryptodome中的以下代码:

 79   if len(key_in) not in key_size:
 80            raise ValueError("Not a valid TDES key")
..
186  # Size of a key (in bytes)
187  key_size = (16, 24)

您的密钥长 16 个字节,但您传递的密钥的十六进制形式的大小为 32。

这里的断开是 pyDes.triple_des() 正在寻找一个二进制密钥,但你给它的是一个编码字符串,带有该密钥的十六进制表示。由于 pyDes 不期望十六进制字符串,请尝试只给它原始摘要(即 m.digest() 而不是 m.hexdigest())。也不需要.encode()