Skip to content

Instantly share code, notes, and snippets.

@jpralves
Created January 14, 2020 23:39
Show Gist options
  • Select an option

  • Save jpralves/505e653fd1c7358ad2c540e25e1ee80a to your computer and use it in GitHub Desktop.

Select an option

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

jpralves commented Dec 2, 2021 via email

Copy link
Copy Markdown
Author

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