How to detect a failed AES256 encryption programmatically?Uu LGoi C
I have implemented a simple encryption/decryption program based on AES256 in CBC mode1.
Actually, it is more precise to describe it as a compression+encryption / decryption+decompression program.
If one provides the wrong key to the decryption+decompression function, the decompression stage will explicitly fail, as expected, since the decrypted content (being based on the wrong key) will be just noise.
I would like modify the decryption phase of the scheme so that it detects on its own that the wrong key has been used, before it proceeds to the decompression phase. I am looking for a scheme to support to do this functionality that does not weaken the overall cryptographic strength of the framework.
A naive approach would be to generate the encrypted content as2
AES256_CBC(key, iv, SENTINEL_STRING + plaintext)
where SENTINEL_STRING is a string that the decryption phase can know in advance. While I am being naive about it, I could make the SENTINEL_STRING be equal to the key, for example.
I imagine there are pretty standard ways to solve this problem. In fact, for all I know, the design of AES256-CBC already has built into it a way to check that decryption succeeded.
I hope someone can enlighten me on these matters.
Also, if this problem is common enough to have a generally accepted name (suitable as search engine fodder) please let me know.
1 For what it's worth, my current implementation of this uses Python's pycrypto module, but an earlier implementation used Perl's Crypto::CBC package. Both versions can reciprocally decrypt+decompress files compressed+encrypted by the other. I bother mentioning all this to stress the fact that this question is primarily about AES256-CBC in general, and not about any specific implementation of it.
2 I hope my ad-hoc notation here is not too stupid. I mean it as shorthand for "encrypt the string SENTINEL_STRING + plaintext with AES256 in CBC mode, using key key and initialization vector iv".
-
$\\begingroup$ CBC mode is vulnerable to padding oracle attacks and it is removed in TLS 1.3. In TLS 1.3, we have only Authenticated Encryption (AE) modes like AES-GCM and ChaCha-Poly1305. It better to switch since AE gives you not only confidentiality but also integrity and authentication. $\\endgroup$ – kelalaka 5 mins ago
1 Answer
You should use an authenticated encryption mode. There are several reasons for that, but one (relatively minor) one is that it automatically gives you the ability to detect incorrect keys, since the authentication will fail.
If you insist on using a traditional non-authenticated encryption mode, or if you'd like to have some way of distinguishing "incorrect key" from "corrupted ciphertext", you can include a key check value together with the ciphertext, and verify it before attempting decryption. There are several possible ways to implement one.
A traditional method is to encrypt an all-zero block using the raw block cipher (i.e. "ECB mode") and use the resulting ciphertext as the key check value, but note that this makes it possible for an attacker to tell whether two messages have been encrypted using the same key by comparing the key check values. Alternatively, assuming that you're using an authenticated encryption mode anyway, you could just generate the key check value by encrypting an empty message using the same mode. Assuming that you're using a unique nonce / IV for each encryption, as you should be, this should eliminate the information leak by making every key check value also unique.
(BTW, note that compressing data before encryption can leak (extra) information about the plaintext. Basically, this happens because all general-purpose encryption schemes necessarily leak information about the length of the plaintext, and compression makes the plaintext length depend on its content. Padding reduces this leak slightly, but does not eliminate it. This has been used in actual attacks.)
-
$\\begingroup$ Thank you, that's very informative. The application I have in mind is long-term off-line storage of sensitive data. Therefore, the primary threat under consideration is that an unauthorized agent gains access to the storage media. All that I've read on authentication strikes me as not applicable to our threat scenario (but this could easily be just a sign of my lack of imagination). Regarding generating a key check value, what about encrypting the (nonce) IV with the raw block cipher? $\\endgroup$ – kjo 7 hours ago