I've spent the night reversing the implementation of the 'Basic Text Encryptor' from Jasypt . The algorithm is defined in documentation as 'PBEWithMD5AndDES'.
The implementation is this:
- A random 64-bit salt is generated
- The secret is generated as
secret = password + salt for i in range(0, 1000): secret = md5(secret)
- The first 8 bytes of the secret are then used as the DES passphrase, and the last 8 bytes of the secret are used as the IV, and used to encrypt data with DES-CBC.
Given this, am I correct in thinking the total keyspace for the implementation is 120 bits (56+64)?
I have written a proof of concept reversal in python, but I'm interested in calculating how long it would take to brute force a real key. So far I've been unable to induce hashcat into decrypting something encrypted with this algorithm, and I'm unsure if it even can.
My questions are:
- Is the keyspace really 120 bits?
- Am I missing something or is hashcat not capable of cracking this?
- Can other tools crack it?
- Is it even possible to deduce correct outputs without making assumptions on expected output (eg all output must be ASCII data, or match a file header)
Edit: To reduce any confusion, my decryptor is as follows
import base64 import hashlib from Crypto.Cipher import DES passphrase = "123456" # Key used to encrypt # Salt randomly generated at encrypt-time, and stored at # the beginning of the encrypted data: salt = base64.b64decode("vqmy2fiCipU=") enc_b64 = "vqmy2fiCipVBIhiAzDfvTL0301DLgTqd" enc_data = base64.b64decode(enc_b64) if (salt != enc_data[0:8]): raise Exception("Salt does not match enc_data salt") enc_data = enc_data[8:] m = hashlib.md5() m.update(passphrase.encode()) m.update(salt) result = m.digest() for i in range(1, 1000): m = hashlib.md5() m.update(result) result = m.digest() # value of result is: md5("123456" + salt) iterated 1,000 times. key = result[:8] iv = result[8:16] des = DES.new(key, DES.MODE_CBC, iv) print(des.decrypt(enc_data).decode()) # > Hello World