# KCV scheme that encrypts a hash over key and IV

Is there anything wrong with this key-check value scheme?

This question is a follow-up to an earlier question of mine. In summary, I want to devise a key-check value scheme that will enable my decryption function, when given a key K and a cyphertext C, to determine whether K is actually the key used to generate C, and to do so without having to decrypt all of C.

At the time of encryption, a key K and a nonce initialization vector IV are available (in addition to the plaintext P). Define KCV as follows:

KCV = encrypt(key=sha256(IV || K), plaintext=IV)


...where encrypt stands for AES256 encryption in ECB mode, and IV || K stands for the concatenation of IV and K. Both IV and KCV will be stored in a header right before the encrypted "payload" C.

At the time computing decrypt(key=K, header=H, ciphertext=C), the program will first read IV from the header H, use it and K to compute an expected KCV, and compare the latter with the KCV stored the header H.

Are there any obvious problems with this scheme? In particular, is there a feasible way to deduce K based on the knowledge of KCV and IV?

• For a key check value I'd use a KDF with a large magic rather than encrypt. Finding the key is unlikely: both the cipher and hash are designed not to leak information. However, the encrypt with IV is problematic, for instance, if you'd use CBC then you would actually nullify the plaintext. Now since the key is still dependent on the IV and K that's not a huge problem, but I would frown if I saw it in any specification. – Maarten Bodewes Oct 24 '19 at 0:11
• Including the IV is weird anyway, as it is part of the ciphertext and is verified within authenticated encryption anyway. – Maarten Bodewes Oct 24 '19 at 0:13
• @MaartenBodewes: thank you for your comments. I am explicitly avoiding authenticated encryption (or rather, avoiding the verification feature of authenticated encryption) because I want to be able to do this key check without having to process the whole ciphertext (which in my use case can be hundreds of GBs in size). As far as I understand, with AE, verification entails processing the full payload, so I don't want to use it for the key check. – kjo Oct 24 '19 at 1:36
• @MaartenBodewes: pardon the dumb question, but what do you mean by a (large) "magic"? – kjo Oct 24 '19 at 1:44
• Skip the block cipher keychange and make it a 1-way transform... KCV = Truncate(HMAC[ Encrypt_k(0x00..00) || IV, "KCV"]) – Richie Frame Oct 24 '19 at 2:01