For example, if we run this openssl command:

openssl aes-128-ecb -a -in <(echo -n "AAAAAAAAAAAAAAAA") -K "deadbeefdeadbeefdeadbeefdeadbeef"

The output in hex looks like:

block 1                          block 2
7a03acccf884d4ac38b7a2f3529806fa adfbc6ad78223f79cded6638d1d9802b

If I run it again and change the last byte, I get:

openssl aes-128-ecb -a -in <(echo -n "AAAAAAAAAAAAAAAa") -K "deadbeefdeadbeefdeadbeefdeadbeef"

block 1                         block 2
0c6b99d8659660bb763ca8a442948da4 adfbc6ad78223f79cded6638d1d9802b

Note the second block is identical. If we decrypt just that block, we get the expected PKCS7 padding of 16 (0x10) repeated (i.e. "10101010101010101010101010101010")

echo "adfbc6ad78223f79cded6638d1d9802b" | xxd -r -p | openssl aes-128-ecb -d -K "deadbeefdeadbeefdeadbeefdeadbeef" -nopad | xxd -p

# gives

However, if we replace the last byte with a character that's 128 or over, we get a different second block. (Note € is ASCII 128)

openssl aes-128-ecb -a -in <(echo -n "AAAAAAAAAAAAAAA€") -K "deadbeefdeadbeefdeadbeefdeadbeef" | base64 -d | xxd -p -c100

block 1                          block 2
2ec43df437eeed3a67a3390e53be7040 2999ee9243fefd95a9b3214cec97e13f

That second block decrypted is "82ac0e0e0e0e0e0e0e0e0e0e0e0e0e0e" which corresponds to 130, 172, and then 14 (i.e. 2 bytes of information and the rest padding).

I'm really confused about where those 2 bytes are coming from, and I can't seem to find any mention of this behavior when googling around.

Does anyone know why this happens?


1 Answer 1


(Note € is ASCII 128)

This is incorrect. Proper ASCII is a 7-bit encoding, there is no 128th element there. The Euro sign (€) is decimal 128 in some extended-ASCII encodings, most famously Windows-1252. However, your Linux system is very likely using UTF-8. There, the Euro sign will be encoded as three bytes 0xE282AC:

~$ echo -n "€" | xxd -p

Thus your input is 18 bytes long, meaning two bytes "spill over" into the second block, which will then have a padding of 14 bytes of value 14 - ie 0x0E.

  • $\begingroup$ That was my issue! thank you. When I feed the hex in via xxd the 2nd block matches. echo "41414141414141414141414141414180" | xxd -r -p | openssl aes-128-ecb -K "deadbeefdeadbeefdeadbeefdeadbeef" | xxd -p -c 100 $\endgroup$
    – carleton
    Commented Jan 21, 2023 at 20:00
  • $\begingroup$ I originally came across this doing some crypto in Javascript and there is something truly terrible going on. There are 2 euro symbols that will render fine in my browser field: and €. One of them is the utf-8 valid one, the other I think is UTF-16, which if I try to copy paste into the URL bar which has I guess stricter encoding checks, it gives me the question mark block. Very strange! (edit: the first one doesn't show up on submit!) $\endgroup$
    – carleton
    Commented Jan 21, 2023 at 20:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.