Replicate Java's Pbewithmd5anddes In Python 2.7
If it's not immediately obvious, let me start by saying I am not a crypto person. I have been tasked with replicating the behavior of Java's PBEWithMD5AndDES (MD5 digest with DES e
Solution 1:
Thanks to GregS's comment, I was able to sort this conversion out!
For future reference, this Python code mimics the behavior of the Java code above:
from Crypto.Hash import MD5
from Crypto.Cipher import DES
_password = 'q1w2e3r4t5y6'
_salt = '\x80\x40\xe0\x10\xf8\x04\xfe\x01'
_iterations = 50
plaintext_to_encrypt = 'MyP455w0rd'# Pad plaintext per RFC 2898 Section 6.1
padding = 8 - len(plaintext_to_encrypt) % 8
plaintext_to_encrypt += chr(padding) * padding
if"__main__" == __name__:
"""Mimic Java's PBEWithMD5AndDES algorithm to produce a DES key"""
hasher = MD5.new()
hasher.update(_password)
hasher.update(_salt)
result = hasher.digest()
for i inrange(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:8], DES.MODE_CBC, result[8:16])
encrypted = encoder.encrypt(plaintext_to_encrypt)
print encrypted.encode('base64')
This Python code outputs the following in Python 2.7:
Icy6sAP7adLgRoXNYe9N8A==
Thanks again to GregS for pointing me in the right direction!
Solution 2:
For Python 3.6, I tested with following code and it works with a little change from above:
from Crypto.Hash import MD5
from Crypto.Cipher import DES
import base64
import re
_password = b'q1w2e3r4t5y6'
_salt = b'\x80\x40\xe0\x10\xf8\x04\xfe\x01'
_iterations = 50
plaintext_to_encrypt = 'MyP455w0rd'# Pad plaintext per RFC 2898 Section 6.1
padding = 8 - len(plaintext_to_encrypt) % 8
plaintext_to_encrypt += chr(padding) * padding
if"__main__" == __name__:
"""Mimic Java's PBEWithMD5AndDES algorithm to produce a DES key"""
hasher = MD5.new()
hasher.update(_password)
hasher.update(_salt)
result = hasher.digest()
for i inrange(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:8], DES.MODE_CBC, result[8:16])
encrypted = encoder.encrypt(plaintext_to_encrypt)
print (str(base64.b64encode(encrypted),'utf-8'))
decoder = DES.new(result[:8], DES.MODE_CBC, result[8:])
d = str(decoder.decrypt(encrypted),'utf-8')
print (re.sub(r'[\x01-\x08]','',d))
Output:
Icy6sAP7adLgRoXNYe9N8A==
MyP455w0rd
Solution 3:
I found one from here
import base64
import hashlib
import re
import os
from Crypto.Cipher import DES
defget_derived_key(password, salt, count):
key = password + salt
for i inrange(count):
m = hashlib.md5(key)
key = m.digest()
return (key[:8], key[8:])
defdecrypt(msg, password):
msg_bytes = base64.b64decode(msg)
salt = '\xA9\x9B\xC8\x32\x56\x35\xE3\x03'
enc_text = msg_bytes
(dk, iv) = get_derived_key(password, salt, 2)
crypter = DES.new(dk, DES.MODE_CBC, iv)
text = crypter.decrypt(enc_text)
return re.sub(r'[\x01-\x08]','',text)
defencrypt(msg, password):
salt = '\xA9\x9B\xC8\x32\x56\x35\xE3\x03'
pad_num = 8 - (len(msg) % 8)
for i inrange(pad_num):
msg += chr(pad_num)
(dk, iv) = get_derived_key(password, salt, 2)
crypter = DES.new(dk, DES.MODE_CBC, iv)
enc_text = crypter.encrypt(msg)
return base64.b64encode(enc_text)
defmain():
msg = "hello"
passwd = "xxxxxxxxxxxxxx"
encrypted_msg = encrypt(msg, passwd)
print encrypted_msg
plain_msg = decrypt(encrypted_msg, passwd)
print plain_msg
if __name__ == "__main__":
main()
Solution 4:
If you're using the newer Cryptodome library with Python 3, you'll need to also encode your plaintext_to_encrypt to 'latin-1', as is shown below.
from Cryptodome.Hash import MD5
from Cryptodome.Cipher import DES
import base64
import re
_password = b'q1w2e3r4t5y6'
_salt = b'\x80\x40\xe0\x10\xf8\x04\xfe\x01'
_iterations = 50
plaintext_to_encrypt = 'MyP455w0rd'# Pad plaintext per RFC 2898 Section 6.1
padding = 8 - len(plaintext_to_encrypt) % 8
plaintext_to_encrypt += chr(padding) * padding
if"__main__" == __name__:
"""Mimic Java's PBEWithMD5AndDES algorithm to produce a DES key"""
hasher = MD5.new()
hasher.update(_password)
hasher.update(_salt)
result = hasher.digest()
for i inrange(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:8], DES.MODE_CBC, result[8:16])
encrypted = encoder.encrypt(plaintext_to_encrypt.encode('latin-1')) #encoded plaintextprint (str(base64.b64encode(encrypted),'utf-8'))
decoder = DES.new(result[:8], DES.MODE_CBC, result[8:])
d = str(decoder.decrypt(encrypted),'utf-8')
print (re.sub(r'[\x01-\x08]','',d))
Post a Comment for "Replicate Java's Pbewithmd5anddes In Python 2.7"