Skip to content

Instantly share code, notes, and snippets.

@jpralves
Created January 14, 2020 23:39
Show Gist options
  • Save jpralves/505e653fd1c7358ad2c540e25e1ee80a to your computer and use it in GitHub Desktop.
Save jpralves/505e653fd1c7358ad2c540e25e1ee80a to your computer and use it in GitHub Desktop.
Python 3 implementation of PBEWITHMD5andDES Java
from Crypto.Hash import MD5
from Crypto.Cipher import DES
import base64
import random
import sys
def randomBytes(n):
return bytearray(random.getrandbits(8) for i in range(n))
def jdkPBE_cipher_PBEWITHMD5andDES(password, plaintext):
bs = 8
_iterations = 1000
data = bytes(plaintext.encode())
padding = bs - (len(data) % bs)
data += bytes((chr(padding) * padding).encode())
salt = randomBytes(bs)
hasher = MD5.new()
hasher.update(bytearray(password.encode()))
hasher.update(salt)
result = hasher.digest()
for i in range(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:bs], DES.MODE_CBC, result[bs:bs*2])
encrypted = encoder.encrypt(data)
return salt+encrypted
def jdkPBE_decipher_PBEWITHMD5andDES(password, data_to_decrypt):
bs = 8
_iterations = 1000
salt = data_to_decrypt[:bs]
data = data_to_decrypt[bs:]
hasher = MD5.new()
hasher.update(bytearray(password.encode()))
hasher.update(bytearray(salt))
result = hasher.digest()
for i in range(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:bs], DES.MODE_CBC, result[bs:bs*2])
decrypted = encoder.decrypt(bytes(data))
length = len(decrypted)
unpadding = int(decrypted[length-1])
if length - unpadding > 0:
return decrypted[:(length - unpadding)].decode()
else:
return decrypted.decode()
def jdkPBE_decipher(ciphername, password, src):
if ciphername == "PBEWITHMD5andDES":
return jdkPBE_decipher_PBEWITHMD5andDES(password, base64.b64decode(src))
else:
raise Exception('unable to decode with {}'.format(ciphername))
def jdkPBE_cipher(ciphername, password, src):
if ciphername == "PBEWITHMD5andDES":
return base64.b64encode(
jdkPBE_cipher_PBEWITHMD5andDES(password, src)).decode()
else:
raise Exception('unable to encode with {}'.format(ciphername))
if "__main__" == __name__:
if len(sys.argv) == 2 and sys.argv[1] == 't':
_password = 'strangepassword'
_cypherdata = 'ZJCmwXlI2Uybx+GwocCD5GxmScwLHDWKM9IO7PXkX4' \
'1lAhkN3wAWV/8q9jeV7K0dFKo4/NWphE37YiLga2RT' \
'uWlWh5Jvxv6s'
_plaintext_to_encrypt = 'João Alves was here'
_encrypted = jdkPBE_cipher('PBEWITHMD5andDES',
_password,
_plaintext_to_encrypt)
print('Encrypting [{}] with password [{}] '
'using PBEWITHMD5andDES -> [{}]'
.format(_plaintext_to_encrypt, _password, _encrypted))
_encrypted2 = jdkPBE_cipher('PBEWITHMD5andDES',
_password,
_plaintext_to_encrypt)
_decrypted2 = jdkPBE_decipher('PBEWITHMD5andDES',
_password,
_encrypted2)
print('Encrypting and Decrypting the [{}] with password [{}] '
'using PBEWITHMD5andDES -> [{}]'
.format(_plaintext_to_encrypt, _password, _decrypted2))
_decrypt_cypher = jdkPBE_decipher('PBEWITHMD5andDES',
_password,
_cypherdata)
print('Decrypting [{}] with password [{}] '
'using PBEWITHMD5andDES -> [{}]'
.format(_cypherdata, _password, _decrypt_cypher))
exit(0)
if len(sys.argv) < 5:
print('''Args: operation ciphername password msg
Ex. to encrypt: e PBEWITHMD5andDES simplepass "Test"
Ex. to decrypt: d PBEWITHMD5andDES simplepass pkRuP5Q6b6ttjEdSF0IBbw==
''')
exit(1)
operation = sys.argv[1]
ciphername = sys.argv[2]
password = sys.argv[3]
src = sys.argv[4]
if operation == "e":
msg = jdkPBE_cipher(ciphername, password, src)
print(msg)
if operation == "d":
msg = jdkPBE_decipher(ciphername, password, src)
print(msg)
@jpralves
Copy link
Author

jpralves commented Dec 2, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment