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.
Post History
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 de...
#1: Initial revision
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: ```python 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: ```python 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?