# How can I do a brute force (ciphertext only) attack on an CBC-encrypted message?

Given a CBC ciphertext and IV, how can I find the encryption key?

We are limited with an 8 chars key, each char in the range of [a..h], so I can generate every possible key (these are only $8^8 = 2^{24}$ (about 4 million) different possible keys).

How would I go about finding the correct one though?

-

## migrated from stackoverflow.comApr 18 '12 at 17:49

This question came from our site for professional and enthusiast programmers.

What have you tried? Is this homework? – Cameron Skinner Apr 17 '12 at 19:17
Yes this is homework. I tried thinking ways of using a dictionary - possibly downloading an english wordlist and trying to encrypt a word with every possible key, but that sounds very unrealistic – antisane Apr 17 '12 at 19:21
How many chars long is the ciphertext? In other words, how many cipher blocks are being generated? – Adam Liss Apr 17 '12 at 22:52
Do you know which padding mode was used, and how long the plaintext and/or ciphertext are? – CodesInChaos Apr 18 '12 at 18:32
Welcome to Cryptography Stack Exchange. Your question was migrated here because of being not directly related to software development (the topic of Stack Overflow), and being fully on-topic here. Please register your account here, too, to be able to comment and accept an answer. – Paŭlo Ebermann Apr 18 '12 at 18:58

In addition to the plaintext analysis given in detail by Ilmari, a first step after trial-decrypting is to check the padding mode.

As you are using a block cipher in CBC-mode, the size of the plaintext must be brought to a multiple of the block size. This is done by a padding mode. A common padding mode (being uniquely reversible) is PKCS#5-padding: Append as many bytes as necessary to come to a full multiple of the block size, but at least one, and have all these bytes have the same value, namely the number of appended bytes.

When decrypting, you then can check if the last $n$ bytes all have the same value $n$. For a wrong key, in about $\frac1{256}$ of all cases this will end with $1$, in $\frac{1}{256·256}$ of all cases it will end with $2,2$, and so on, and then you'll have to check the rest of the decrypted plaintext to see if it is plausible (see the answer from Ilmari for details). In all other cases you know immediately that the key is wrong. (Of course, this only useful if you know (or can guess) the padding scheme.)

Note that with CBC, you can decrypt the last block without decrypting all the other blocks - just do Decrypt(key, last block) ⊕ before-last block to get the plaintext.

-

If (you suspect that) the (plaintext of the) encrypted data is ASCII text, you can check if the high bit of each decrypted byte is zero. As long as you have more than 24 bytes of data to check, the odds of that happening by chance are pretty low (given that you have a 24-bit keyspace).

UTF-8 text is also pretty easy to detect, since all bytes that do have the high bit set can only occur in a very distinctive pattern.

More generally, if you decrypt something with the wrong key, the output will look random, and thus all bytes (and all sequences of n bytes) will appear on average about equally often. If you get output that deviates significantly from this (where significance can be measured e.g. using Pearson's χ2 test), it will most likely be the correct plaintext.

For small amounts of data, it may be useful to apply this test not only to the full bytes but also to their highest and/or two (and maybe even three) highest bits. This will detect byte values that cluster together (as e.g. letters and numbers do in ASCII), even if there are not enough bytes in the data to get many exact repeats. You can also try looking at the differences between two successive byte values (modulo 256) to detect correlations. All these (and many other variations of them) should be uniformly distributed for random data, whereas many of them will show distinct deviations from uniformity for most kinds of non-random data.

-
Encrypted data is binary; each byte can have a value from 0 - 255. How does the MSB of the ciphertext reflect the input data? – Adam Liss Apr 17 '12 at 22:54
Sorry, I wrote "encrypted" when I meant "decrypted". Fixed. – Ilmari Karonen Apr 17 '12 at 23:00
­@Ilmari Karonen Ok, now what if the "plaintext" is not actually text, but a file of unknown type (image, music, etc.) or even an other ciphertext (using an other cipher for instance), it would be indistinguishable from random noise, so impossible to guess it's the "plaintext" we've got ? – MaxiWheat Jun 26 '13 at 13:41
@MaxiWheat: Most image / music / video / etc. file formats start with a fixed and distinctive header, which is how your computer can tell how to play each file correctly. In fact, the same goes for most compression and/or encryption formats too. If you have some idea what the type of the file is, you can just decrypt the first few blocks and look for the correct header. If not, you can always just try to match the decrypted data against a list of common file headers, like the one used by the Unix file command. – Ilmari Karonen Jun 26 '13 at 13:49
Great, I expected such an answer, I just wanted to clarify ;-) But I'm more interested in that "double encryption" scenario. In my understanding, it's impossible to know we got the right "first key" in a brute force attack if the plaintext was encrypted twice (with different ciphers and keys). The brute force attack should perform the two decryptions (with two keys) and then evaluate if it found the plaintext. Am I right ? – MaxiWheat Jun 26 '13 at 14:13