Why does OpenSSL append extra bytes when encrypting with aes-128-ecb? Plaintext:

Attack at dawn!!


Hex:

41747461636b206174206461776e2121


Key: 

abcdefghijklmnop


Hex: 

6162636465666768696a6b6c6d6e6f70)


Through calculations done both by hand and with various sites online, the result should be:

379693884e25f00f6e8aaa43df4db541


The result is the same length as the input, byte-for-byte.

I tried to recreate this result using OpenSSL with the following:

echo 'Attack at dawn!!' | openssl enc -aes-128-ecb -K 6162636465666768696a6b6c6d6e6f70 -nosalt -out out.bin


The output is:

379693884e25f00f6e8aaa43df4db541
8e64ce873f174dbb2423fcd814580e15


The fact that the first 16 bytes of the OpenSSL result is the same the by-hand calculations shows me that I'm on the right track.

My question is: What are the remaining "extra" 16 bytes for?
First, your use of 'echo' gets you: 

~ % echo 'Attack at dawn!!' | hexdump -C
00000000  41 74 74 61 63 6b 20 61  74 20 64 61 77 6e 21 21  |Attack at dawn!!|
00000010  0a                                                |.|
00000011


Note that there are 17 bytes there, not 16. echo adds a newline character. To stop that, use the -n flag:

~ % echo -n 'Attack at dawn!!' | hexdump -C
00000000  41 74 74 61 63 6b 20 61  74 20 64 61 77 6e 21 21  |Attack at dawn!!|
00000010


If you use the -v flag with openssl enc, it will tell you how many bytes were read: 

~ % echo 'Attack at dawn!!' | openssl enc -v -aes-128-ecb -K 6162636465666768696a6b6c6d6e6f70 -nosalt -out out.bin
bytes read   :      17
bytes written:      32


So that would have been an indicator of something being wrong. The echo problem isn't the only one, though; we still have two blocks of output despite only having one block of input: 

~ % echo -n 'Attack at dawn!!' | openssl enc -v -aes-128-ecb -K 6162636465666768696a6b6c6d6e6f70 -nosalt | hexdump -C
bytes read   :      16
bytes written:      32
00000000  37 96 93 88 4e 25 f0 0f  6e 8a aa 43 df 4d b5 41  |7...N%..n..C.M.A|
00000010  8e 64 ce 87 3f 17 4d bb  24 23 fc d8 14 58 0e 15  |.d..?.M.$#...X..|
00000020


The second issue is that OpenSSL uses PKCS#7 padding to ensure there are full blocks. In this padding scheme, padding is always applied. So, in the case of a full input block, another full block of 0x10 bytes will be added as padding, which means you'll have two blocks of output (which is what you see above).

The -nopad option for openssl enc disables padding (but it will throw an error if your input isn't a multiple of the block size):

~ % echo -n 'Attack at dawn!!' | openssl enc -aes-128-ecb -K 6162636465666768696a6b6c6d6e6f70 -nosalt -nopad | hexdump -C 
00000000  37 96 93 88 4e 25 f0 0f  6e 8a aa 43 df 4d b5 41  |7...N%..n..C.M.A|
00000010