# DES-CBC with random IV - how big is the keyspace? Can COTS tools crack it?

I've spent the night reversing the implementation of the 'Basic Text Encryptor' from Jasypt [1]. 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


• IV is never mean to be secret. For CBC mode it should be an unpredictable nonce. The single DES key is 56 bits Apr 30, 2020 at 15:07
• I understand that's the intent, but in the context of this implementation, IV is secret. Apr 30, 2020 at 22:37
• All the security analyses of CBC mode assume the IV is public, and only the key is secret. So you can't assume the security changes without doing a new analysis. May 1, 2020 at 14:35

Is the keyspace really 120 bits?

No. It's still 56 bits, at least when multiple blocks are encrypted. For CBC mode then you can try and decrypt a block with the key, XOR it with the previous ciphertext block you should get a plaintext block. If you did this for the last plaintext block you'll have the PKCS#5 padding to find. If that's correct then you can start looking if you can produce valid plaintext.

If only one block is encrypted then the IV acts as a one-time-pad. In that case you will have to guess the password (presuming you have the salt of course).

Am I missing something or is hashcat not capable of cracking this?

Could be. But it would probably not be that hard for an accomplished programmer to program it in. Hashcat seems to focus on the password hash itself. Assuming the password is not too complex, guessing it may still be the best way to try and decrypt the ciphertext.

Can other tools crack it?

Well, cracking single DES can be done by specialized hardware for sure (a list is here). Asking for resources like that is off-topic though.

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)

Well, other than the padding, yes, you must be able to test if the plaintext is comprehensible in some kind of way. However, if you decrypt many blocks the plaintext is likely not all that random, so you could test for that. If it compresses well, for instance, it may be worth another look (but compression is generally pretty expensive).

• Uh, this is the best I can do. I'm no expert on hashcat or such tooling. May 1, 2020 at 0:35
• Hey thanks for responding I really appreciate the help. I'm a bit unclear on what you mean by 'you can try and decrypt a block with the key, XOR it with the previous ciphertext block' - are you suggesting brute forcing the last block and XOR-ing backwards from there? May 1, 2020 at 4:47
• No, for each step of the brute forcing you have to XOR with the previous ciphertext block. Look into how CBC mode decryption works. May 1, 2020 at 12:15
• To confirm, the IV is secret and not disclosed along with the message - is this your understanding? I'm still unclear on how I would crack any block without the IV. May 2, 2020 at 12:42
• In CBC mode a block of ciphertext only depends on the previous block of ciphertext and the plaintext during decryption. So if you don't know the IV, then you can just not decrypt the first plaintext block. Type in CBC mode of operation, go to Wikipedia, and lookup CBC mode decryption. May 2, 2020 at 22:55