7

I am newbie to CBC crypto: When I try decrypt the cipher text to recover the plain text, things are not going smoothly as I face some issues in the decryption process with padding and not obtaining the plain text finally.

So I would like to know about why padding is used in this CBC method? Why is it not used in the ECB method? Should we pass padding for the decryption process?

Below are the cipher text and IV which I have used in my testing:

cipher text(hex) - 6d 25 1e 90 44 b0 51 e0 4e aa 6f b4 db f7 84 65

Initialization Vector(hex) - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Expected Plain text(hex) - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Could someone try this ciphertext and IV and share the results?

Key size: 16;

Key used in hex: 10a58869 d74be5a3 74cf867c fb473859

danny
  • 253
  • 1
  • 2
  • 12
  • 1
    And what key are you using? If it were the all-zero key, you should have 8A05FC5E095AF4848A08D328D3688E3D as a ciphertext... You can test your AES-CBC using the test vectors one can find all over the internet. For example here. – Lery Jun 26 '17 at 08:24
  • Hello Lery, could you please check are you getting expected plain text with the key mentioned? Thanks for your response – danny Jun 26 '17 at 10:37
  • 1
    I've completed my answer with a practical part. But it works fine for me, as long as I don't forget to "reset" the IV back to its original value before decryption. – Lery Jun 26 '17 at 12:35
  • 2
    Are you sure the ciphertext is not "6d 25 1e 69 44 b0 51 e0 4e aa 6f b4 db f7 84 65"? – fgrieu Jun 26 '17 at 18:14

1 Answers1

20

So, I'll answer the theoretical part of your question, since we need a key to address the practical part.

Why is padding used in CBC?

Blockcipher such as AES are encrypting blocks of a fixed given size only, we call it the "blocksize". So, what if your data is smaller than the blocksize ? An easy solution is to add what we call "padding" to your plaintext in order to have its size match the block size. So, padding is there to allow you to encrypt data smaller than the blocksize... But what if you want to encrypt something bigger than your blocksize?

That's where the mode of operations, such as CBC, come into play. Modes of operations are there to allow you to encrypt more data than the blocksize of your symmetric blockcipher.

But since those modes of operation are still using the underlying blockcipher to encrypt data, it means that they can only encrypt a multiple of the blocksize. So, if you have $4\ell$ bits of data to encrypt, for $\ell$ the block size of your cipher, then you're fine. But what if you have $4\ell+5$ bits of data? (I am assuming the blocksize does not divide 5.) Then you need to pad the data with $\ell-5$ bits of padding in order to end up with a multiple of the blocksize of data ready for encryption with your mode of operation.

There are multiple methods to pad data, which can completely undermine the compatibility of a given encryption program with others. The most used padding method in symmetric ciphers and mode of operation is certainly PKCS#7.

Worth noting

There exists methods to avoid padding, in order to avoid padding completely so the ciphertext is the same size as the plaintext, the most common of those methods is certainly the one called ciphertext stealing.

There also exists modes of operation, such as CTR, which do not need any padding.

Now, contrarily to RSA encryption for instance, padding in symmetric encryption does not add security.

Checking the padding upon decryption can allow to catch errors in the transmitted ciphertext, because of the avalanche effect, (depending on the mode of operation used), but can also lead to terrific padding oracle attacks.

As explained in that question, it is better to use a cryptographic MAC to protect your ciphertext, and verify it first before performing decryption or even padding checks. I also refer you to that legendary question, regarding the way one should MAC its data when using encryption.

About ECB

Actually ECB also encrypts only multiples of the blocksize, so you will also need padding or another method to have enough data to encrypt. However, you should not use ECB for the reasons pointed out there.


Regarding your practical problem

So, I've tried your values:

from Crypto.Cipher import AES
import binascii

key = binascii.unhexlify("10a58869d74be5a374cf867cfb473859")
iv = binascii.unhexlify(16*"00")

plaintext = binascii.unhexlify(16*"00")
ciphertext = binascii.unhexlify("6d251e9044b051e04eaa6fb4dbf78465")

ciph = AES.new(key, AES.MODE_CBC, iv)

test1 = ciph.encrypt(plaintext)
print("The ciphertext is what we expected:", test1==ciphertext)    

#We need to reset the cipher to get the correct IV
ciph = AES.new(key, AES.MODE_CBC, iv)

test2 = ciph.decrypt(ciphertext)
print("The recovered plaintext is what we expected:", test2 == plaintext)

and as you can see if you try it with Python and PyCrypto, it works but your ciphertext strangely differ from the actual value at offset 4, as pointed in the comment by fgrieu. The actual value is 69, not 90.

This error at offset 4 explains why you couldn't get the correct recovered plaintext, because of the avalanche effect, the whole AES block was being impacted by that little mistake.

Lery
  • 7,679
  • 1
  • 26
  • 46
  • 1
    Exactly how did you get "6d251e6944b051e04eaa6fb4dbf78465"? It is nowhere to be found in the question, which has the different "6d 25 1e 90 44 b0 51 e0 4e aa 6f b4 db f7 84 65" (in every version that I could find)? – fgrieu Jun 26 '17 at 18:14
  • 1
    sorry that the cipher text is absolutely right as mentioned by lery "6d251e 69 44b051e04eaa6fb4dbf78465" since 90 is not right value. – danny Jun 26 '17 at 18:21
  • 2
    @fgrieu I actually completely missed it and I guess I've wrongly copy-pasted the ciphertext from my terminal instead of the question. You are right that they differ. But I got the actual value when encrypting using the provided parameters. I'll edit it to point it out. – Lery Jun 26 '17 at 18:40
  • 1
    'Why not ECB?' Like CBC, ECB is block-oriented and does require padding for most data; what it does not require is an IV. However, ECB often allows the overall system to be broken, which makes the padding unimportant in comparison. Consider a restaurant with a strict dress code: if you don't wear a jacket and tie you can't eat at all; if you wear it and get an excellent meal, all well and good; if you wear it and get poisoned food, you die and the jacket and tie don't help your corpse. – dave_thompson_085 Jun 27 '17 at 04:26
  • 1
    @dave_thompson_085 Right, I forgot to address this. I've added a quick paragraph on the topic. – Lery Jun 27 '17 at 08:15
  • Hello Lery, could you pls share the Encryption results with pkcs7 padding? I hope cipher text would be different after PKCS7 padding is done... During encryption process, i got the ciphertext at one point as "6d251e6944b051e04eaa6fb4dbf78465" but then at final step i got cipher text as "8964e0b149c10b7b682e6e39aaeb731c"... Could you pls verify the ciphertext with padding as same as you calculate? – danny Jun 27 '17 at 10:19
  • 1
    If you use PKCS7 padding, then when you have a plaintext of the exact blocksize, like you do here, you have to add a full block of padding at the end, so you would not get 16 bytes of output, but 32... So you should get the ciphertext:
    6d251e6944b051e04eaa6fb4dbf78465 881572c3a96a612c111055707bd7614e
    – Lery Jun 27 '17 at 13:15
  • Does the size of cipher text depends of plain text block size when padding is done or is it based on Key size( here 16 bytes of key is used). Shall i assume that when padding is done, Cipher text size would be twice of key size. Cipher text = 2* keysize. Also, Could you pls share the link how padding is implemented here. How to do cbc encrypt with pkcs7 padding in pyCrypto library ? Thanks a lot for replies... You had described this concept exactly what i want.... – danny Jun 28 '17 at 06:36
  • 1
    @danny The size of the ciphertext depends on the size of the plain text. If you have plaintext whose size is a multiple of the blocksize, then you'll have one more block of ciphertext, while otherwise you'll get the same number of blocks than of the plaintext rounded up. If you have a plaintext of size $P$ bits, and a blocksize equal to $\ell$ bits then the size of your ciphertext will be equal to : $\lceil\frac{P+1}{\ell}\rceil\ell$ bits when using PKCS7 padding. You'll find some code there to do PKCS with AES in python. – Lery Jun 29 '17 at 14:51