AES decryption on iOS: populating PKCS5 and CBC

I use some decryption code for iOS for a message coming out on a server that I have no control over. The previous implementation on another platform documents the AES256 decryption requirements, sets the key and initialization vector, and also says:

* Cipher Mode: CBC * Padding: PKCS5Padding 

The CCCryptor object creation options include only kCCOptionPKCS7Padding and kCCOptionECBMode, noting that CBC is the default. From what I understand about the encryption add-on, I donโ€™t understand how to use both; I thought they were mutually exclusive. When creating CCCryptor for decryption, I tried to use both parameters 0 for parameters and kCCOptionPKCS7Padding, but both give me gibberish after decryption.

I compared the dump of this decryption to the dump of the decoded byte buffer on another platform and confirmed that they are really different. Therefore, there is something that I do differently in this implementation, which is significantly different, I just do not know what ... And do not have a clue on how to get a pen on it. The platforms are different, which is difficult to make from the previous implementation, because it is based on a completely different platform. And, of course, the author of the previous implementation has since left.

Any guesses on what else might be incompatible or how to fix this problem?

+8
ios padding aes
source share
4 answers

padding PKCS # 5 and padding PKCS # 7 are almost the same (adding bytes 01 or 0202 or 0303, etc. to the length of the block size algorithm, 16 bytes in this case). Officially, PKCS # 5 padding should only be used for 8-byte blocks, but at many intervals they can be interchanged without problems. Filling always occurs at the end of the ciphertext, so if you get only gibberish, this is not an addition. ECB is a block mode of operation (which should not be used to encrypt data that can be distinguished from random numbers): this will require filling, so they are not mutually exclusive.

Finally, if you just perform decryption (and not MAC'ing or other forms of integrity control), and you return the debug result to the server (decryption failed), your text data is unsafe due to the addition of the oracle attack.

+6
source share

First, you may worry about the supplement later. Providing 0 , as you did, means AES CBC without filling, and with this configuration you should see your message in order. Albiet is potentially with some uppercase bytes at the end. So that leaves:

  • You are not loading the key correctly.
  • You are not loading IV correctly.
  • You are not loading the data correctly.
  • The server does what you do not expect.

To debug this, you need to isolate your system. You can do this by running a loopback test in which you encrypt and then decrypt the data to make sure that you download everything correctly. But this can be misleading. Even if you have something wrong (for example, download the key back), you can still decrypt what you have encrypted, because you are doing it exactly the same way on both sides.

So, you need to test against Known Answer Tests (KAT). You can watch the official KAT on the AES wikipedia entry . But it so happened that I posted another answer here on SO, which we can use.

Given this input:

 KEY: 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f IV: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 PLAIN TEXT: encrypt me CIPHER TEXT: 338d2a9e28208cad84c457eb9bd91c81 

Confirm with a third-party program that you can decrypt the encryption text and get plain text.

 $ echo -n "encrypt me" > to_encrypt $ openssl enc -in to_encrypt -out encrypted -e -aes-256-cbc \ > -K 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \ > -iv 0000000000000000 $ hexdump -C encrypted 00000000 33 8d 2a 9e 28 20 8c ad 84 c4 57 eb 9b d9 1c 81 |3.*.( ....W.....| 00000010 $ openssl enc -in encrypted -out plain_text -d -aes-256-cbc \ > -K 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \ > -iv 0000000000000000 $ hexdump -C plain_text 00000000 65 6e 63 72 79 70 74 20 6d 65 |encrypt me| 0000000a 

So now try decrypting this test with a known answer in your program. Be sure to include the PKCS7 add-on because this is what I used in this example. As an exercise, decrypt it without padding and see that the result is the same, except that you have uppercase bytes after the text "encrypt me".

Implementing KAT is a big step. It says that your implementation is correct, but your assumptions about server behavior are incorrect. And then it's time to start a survey of these assumptions ...

(And PS, the options you mentioned are not mutually exclusive. ECB means no IV, and CBC means you have IV. No relation to filling out.)

Well, I know what this exercise said, but I want to prove that even if you encrypt with padding and decrypt without padding, you don't get garbage. Therefore, given the KAT that used the PKCS7 add-on, we decrypt it without the add-on option and get a readable message, followed by 06 , used as the fill byte.

 $ openssl enc -in encrypted -out plain_text -d -aes-256-cbc \ -K 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \ -iv 0000000000000000 -nopad $ hexdump -C plain_text 00000000 65 6e 63 72 79 70 74 20 6d 65 06 06 06 06 06 06 |encrypt me......| 00000010 $ 
+4
source share

Pavel,
PKCS # 5 gasket is needed to identify padding in decrypted data. For CBC, the input buffer must be a multiple of the size of the encryption block (16 for AES). For this reason, the buffer to be encrypted is supplemented with extra bytes. Please note that after encryption the original data size is lost. PKCS # 5 padding allows you to get this size. This is done by filling the extended data buffer with repeated bytes with a value equal to the size of the fill. for example, if your cleartext buffer was 12 bytes, to make it a multiple of 16, you need to add 4 more bytes. (If the data was 16, you add 16 more to make it 32). Then you fill in these 4 bytes of โ€œ0x4โ€ to match PKCS # 5 expansion. When you decrypt, just find the last byte in the decrypted data and subtract this number from the length of the decrypted buffer.

What you do is fill in "0". Although you seem happy to see the results, you will be surprised when your raw data ends with one of โ€œ0โ€.

+3
source share

It turns out that the explanation of what I was experiencing was awkwardly simple: I misinterpreted what I read in the previous implementation to suggest that it uses a 256-bit key, but in fact it used a 128-bit key. Make this change, and suddenly what was obscure becomes open. :-)

0 for the options argument to invoke CBC was actually right. Which link to the PKCS5 add-on in the previous implementation is still mysterious, but it does not matter, because what works for me now.

Thanks for the shot, indiv.

0
source share

All Articles