DEV Community

Hafiz Muhammad Attaullah
Hafiz Muhammad Attaullah

Posted on

Can You Trust AES Encryption?

In this article, I will not break the AES method (as it has yet to be broken), but breach its integrity. This is because some modes of AES are not good at handling the integrity of the message. The fast stream cipher modes, such as with CTR and GCM are especially prone to this lack of integrity checking, as it is easy to pick off the characters to target.

As a magic trick, I will take the encrypted message of:

Pay Bob 1 dollar
Enter fullscreen mode Exit fullscreen mode

and then flip a few bits to give the ciphertext for:

Pay Bob 2 dollar
Enter fullscreen mode Exit fullscreen mode

In ASCII, a ‘1’ is 0110001, and a ‘2’ is 0110010, and so all I have to do, is to find the place of the character I want to flip in the ciphertext, and then flip the two least significant bits.

First, I will encrypt the message using AES CTR mode — a fast stream cipher mode with AES — and use a passphrase of “Bob123”. The encryption key will be generated using PBKDF2:

$ echo "Pay Bob 1 dollar" | openssl enc -k bob123 -e -aes-128-ctr -pbkdf2 >ciphertext
Enter fullscreen mode Exit fullscreen mode

The ciphertext will be in a binary form:

$ cat ciphertext
Salted__?T????i??k=e??n??.3?%
Enter fullscreen mode Exit fullscreen mode

We can then use xxd to convert this binary format into a ciphertext so that we can edit the ciphertext:

$ xxd ciphertext > data
$ cat data
00000000: 5361 6c74 6564 5f5f f354 1385 819d f1a3  Salted__.T......
00000010: 69fa 816b 3d65 80ed 136e a405 f02e 3307  i..k=e...n....3.
00000020: e6 
Enter fullscreen mode Exit fullscreen mode

AES CTR is a stream mode, so it is easy to find all of the characters in the cipher, as they map straight to their position in the plaintext. Now, we ignore that last byte (e6) and count back the number of characters to the ciphertext of ‘1’. In this case, it is eight characters from the end, so let’s use change the ciphertext to:

(base) billbuchanan@ASecuritySite ~ % cat data
00000000: 5361 6c74 6564 5f5f f354 1385 819d f1a3  Salted__.T......
00000010: 69fa 816b 3d65 80ed 106e a405 f02e 3307  i..k=e...n....3.
00000020: e6 
Enter fullscreen mode Exit fullscreen mode

In this case, I have changed “136e” to “106e”, and only flipped two bits (from 0010011 to 0010000, and which should change a ‘1’ to a ‘2’ ). Now we will convert the cipher back into binary, and decrypt:

% xxd -r data > ciphertext
% cat ciphertext
Salted__?T????i??k=e??n??.3?%
% cat ciphertext | openssl enc -k bob123 -d -aes-128-ctr -pbkdf2   
Pay Bob 2 dollar     
Enter fullscreen mode Exit fullscreen mode

And magically, we have converted one dollar into two!!!!

Why does this happen? Well, the integrity checking in OpenSSL is not very good, and it struggles to detect whether bits have been flipped in the cipher.

Here is the demo:

Overall, CTR and GCM are two of the fastest and widely used modes in AES. Their great advantage is that they convert the block mode into a stream cipher (and thus do not need padding and can be processed in parallel). They are only beaten for performance by ECB, and which has serious weaknesses (as it has no nonce input):

Image description

If you are interested in the performance of AES modes, try here:
https://medium.com/asecuritysite-when-bob-met-alice/whats-the-fastest-symmetric-cipher-and-mode-3d6e77841c2b

Top comments (0)