在 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()
。
我有一个用 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()
。