This is a part of cryptopals challenges (cryptopals.org)
Following code performs the "encrypt" operation on the ciphertext obtained from the previous round:
from Crypto.Cipher import AES
def ecb(plaintext, key):
assert len(plaintext) == 16
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(plaintext)
return ciphertext
if __name__ == '__main__':
testbytes = b'a' * 16
key = b'0' * 16
ciphertext = ecb(testbytes, key)
plaintext = ecb(ciphertext, key)
assert testbytes == plaintext
Theoretically, ECB is so simple, the only difference between encryption and decryption modes is that those plaintext and ciphertext swap places: in encryption, plaintext is input and ciphertext is output, and in decryption, ciphertext is input and plaintext is output, rest is the same. Reasoning from that, "encrypting" ciphertext again should yield plaintext, but this code does not work like that. If I have to guess encrypt
and decrypt
does more than merely applying the block operation. In any case, why doesn't double encryption work as expected?
Shouldn't it be in your code assert testbytes == plaintext
to test your hypothesis?
Anyway. An encryption consists of two parts, the algorithm (here AES) and the mode of operation (here ECB). The algorithm itself can only encrypt a single block. The mode of operation extends this to plaintexts of any length. So that your assumption is correct, the individual processing steps and their order for decryption and encryption must be identical for both parts, algorithm and mode of operation.
Concerning the ECB mode your assumption is true, because each block is processed independently from the other (which also makes this mode insecure). However, for AES your assumption is not true, since decryption is essentially done in the reverse
order to encryption, for details see here.
The easiest way to check the latter is to encrypt only one block without padding. Since the ECB mode does not use an IV, the encryption is reduced to the AES primitive itself. Padding does not have to be disabled, because PyCryptodome does not implicitly pad (in contrast to many other libraries). This case just corresponds to your code (although you have to check the equality between testbytes
and plaintext
). The result verifies that a double encryption using AES does not result in the original plaintext.