Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Is this AES/CBC scheme, where the IV does not need to be known during decryption, insecure or does it have any other disadvantages?
Usually a random IV is used for encryption with AES in CBC mode, so that key/IV pairs are not reused, which would be a vulnerability.
During decryption, the IV of the encryption is required. If decryption is performed with a different IV, this leads to corruption of the first block in CBC mode.
In order to make the IV available to the decrypting party, it is usually concatenated with the ciphertext (IV | ciphertext). During decryption, the IV and ciphertext can then be determined from this.
In Python and with PyCryptodome, one possible implementation is:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
plaintext = b'This is a top secret.'
key = b'01234567890123456789012345678901' # AES test key
cipher = AES.new(key, AES.MODE_CBC)
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
ivCiphertext = cipher.iv + ciphertext # concatenate IV and cipertext
print(ivCiphertext.hex())
iv = ivCiphertext[:16] # strip IV off
ciphertext = ivCiphertext[16:]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
print(plaintext.decode())
Since in the CBC mode only the first block is corrupted when decrypting with a wrong IV, the following scheme would also be possible: The plaintext is preceded by an arbitrary plaintext block, e.g. 16 0x00 values. A random IV is used for encryption. For decryption, an arbitrary IV is used, e.g. 16 0x00 values. The first block of the decrypted plaintext is discarded (this is corrupted due to the wrong IV, but as it does not contain any payload data, this does not matter).
In Python and with PyCryptodome, a possible implementation is the following:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
plaintext = b'This is a top secret.'
key = b'01234567890123456789012345678901' # AES test key
plaintext = b'\x00'*16 + plaintext # prepend arbitrary block
cipher = AES.new(key, AES.MODE_CBC)
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
print(ciphertext.hex())
cipher = AES.new(key, AES.MODE_CBC)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
plaintext = plaintext[16:] # remove prepended block
print(plaintext.decode())
There is practically no difference in the effort required for the two implementations. Neither leads to key/IV reuse. Both must pass data of the same size to the decrypting party. However, the last variant has the advantage (at least in my opinion) that the condition The IV of the encryption is required for decryption is eliminated. Nevertheless, the last scheme is practically not used (at least I can only find the first variant on the web). My questions are: Does the second implementation have a disadvantage in terms of security compared to the first? Or is there another reason why the second schema is not used?
1 answer
However, the last variant has the advantage (at least in my opinion) that the condition The IV of the encryption is required for decryption is eliminated.
It isn't really. It's just generated less efficiently: instead of generating a random IV, the sender has to generate a random IV and do one block's worth of encryption to get the real IV.
0 comment threads