Created
January 14, 2020 23:39
-
-
Save jpralves/505e653fd1c7358ad2c540e25e1ee80a to your computer and use it in GitHub Desktop.
Python 3 implementation of PBEWITHMD5andDES Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Author
jpralves
commented
Dec 2, 2021
via email
Can you provide the code that generates that error?
Regards,
João
…On Mon, 29 Nov 2021 at 11:33, Esteban Sorribas ***@***.***> wrote:
***@***.**** commented on this gist.
------------------------------
Hi Joao,
Thanks for the GIST, I have a question.
When I run the class trying to decode data I have this message:
"Data must be padded to 8 byte boundary in CBC mode"
Do you what is causing this Exception?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<https://gist.github.com/505e653fd1c7358ad2c540e25e1ee80a#gistcomment-3977550>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFCKSEMPMER7GYHONXSL73UONQKJANCNFSM5I64SAFA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
--
<https://about.me/jpralves?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=edit_panel&utm_content=thumb>
João Alves
about.me/jpralves
<https://about.me/jpralves?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=edit_panel&utm_content=thumb>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment