1 Answer
1

Several symmetric block ciphers (specifically ones like AES, DES, Blowfish, RC5) will take the same amount of time (within measurement error) for encryption and decryption, when operating on a single block (e.g., 128-bits for AES).

However, there are a couple reasons why it appears different when encrypting/decrypting multiple blocks. For example, with cipher-block chaining (CBC), encryption must be done sequentially (encrypt block 0 before you can encrypt block 1 before you can encrypt block 2 ...), while decryption can be parallelized as the XOR step (with the previous block of ciphertext) is done after the block cipher is applied.

See the diagrams below (XOR is denoted with a circled plus ⊕). To encrypt the second block of plaintext p[1], you use c[1] = AES_Encrypt(p[1] XOR c[0]), this means you can't generate c[1] until you are finished generating c[0].

Meanwhile to decrypt the second block of ciphertext, you use p[1] = c[0] XOR AES_Decrypt(c[1]). This is not dependent on the previous block of plaintext p[0] so can be completely parallelized (and can run much faster on multi-core systems).

If you want fast decryption and encryption, you may consider using CTR as it can be parallelized on both encryption and decryption.

You also potentially should be wary of tests that are skewed because of caches on your system. If you randomly decide to read a file from disk and encrypt it, it will take several milliseconds to read each chunk of the file; however the next time you access it the file will generally be cached in memory and be accessed much quicker. Meanwhile for your decryption test that encrypted file that was recently written to disk will likely still be in a cache in memory and will not suffer the penalty from reading from disk.

The first three encryptions show the effect of the disk cache, where the first access of a file was much slower than subsequent accesses. It also shows that for CTR that both encryption / decryption of this 7.4 G virtual machine took roughly 35 seconds. (On repetition occasionally, decryption would be faster or slower).

There are block ciphers where encrypt/decrypt have slightly different cost. These aren't just based on external effects like mode, or caches. You could see that difference with ECB mode. Threefish is one of them, but I don't know if this applies to AES as well.
–
CodesInChaosJun 26 '13 at 17:30

1

@CodesInChaos - Good point. I was trying to speak concretely about AES where the steps for encryption / decryption have exact analogs of each other in a decent implementation (Round Key generation / SubBytes vs InvSubBytes / ShiftRows vs InvShiftRows / MixColumns vs InvMixColumns). The similar block ciphers was specifically referring to Luby-Rackoff block ciphers (which AES is not an example of) built from Feistel network should have this property as encryption decryption are the same applications of the same pseudo-random function (just in opposite order to opposite halves of the block).
–
dr jimbobJun 26 '13 at 18:13

3

Just wanted to say that this is a great answer, and I wish there were more like this on the SE network!
–
asteriJun 26 '13 at 19:15

If you use ram (e.g. /tmp) to store the files shouldn't you be able to test without being affected by disk io?
–
Alvin WongJun 27 '13 at 6:21

@CodesInChaos - While I can't demonstrate that all symmetric key ciphers take same time on one block for enc/decrypting. However, looking at threefish's implementation (section 2.2 ), it should take the same time to encrypt/decrypt. Tests in python3 for threefish show the same running time; e.g., encrypting 50000 random 64-byte blocks takes 23.134 +/- 0.183 ms, while decrypting 50000 random 64-byte ASCII blocks takes 23.135 +/- 0.095 ms. Here's a pastebin of the python3 tests.
–
dr jimbobJun 28 '13 at 16:26