-
Notifications
You must be signed in to change notification settings - Fork 0
Nonces
Everyone says the best way to implement your own crypto is "don't". They are right. I thought I had made rivercrypt simple enough that it didn't have any cryptography errors. I was wrong. There was an extremely obvious and rookie mistake I made in format version 3 of rivercrypt, visible in the function encdecroutine. Can you spot the error? I'll wait.
I hadn't incremented the counter in the loop, which caused the same nonce (number only used once) to be used for each and every single block of the encrypted file. This is a major security issue, since if you know one block of the decrypted file, you can use that to decrypt the rest of the file.
I had considered some of the security implications of the nonce, and weighed a couple of issues when deciding on the version 3 format and how it dealt with the nonces. One of the problems was that I needed to use a different nonce for each block, however I didn't know the number of blocks it would encounter before writing the header. So instead of saving each of the nonces into the header, I decided to use a combination of a random nonce and a counter. Part of the nonce for each block would come from a random nonce that is specific to that encrypted file, and the rest of the nonce would be a counter that would start at 0 and increment for each block. The defaults I chose would only allow files less than 512TB to be encrypted (explanation), but would have 5 bytes of nonce randomness, which should provide enough randomness to not repeat it. Though now that I think about it, do I even need to use a different nonce for each file encrypted if none of them use the same encryption key?
For version 4, I wanted something more robust, so I chose to use HMACs for the Nonces. I create a per-file nonce, which then I use as the secret key in an hmac of the counter, as seen in schedule_nonce. This HMAC is truncated, which I assume only reduces the security of the HMAC algorithm in that the difficulty of creating a collision is reduced to the truncated length. This should guarantee a unique nonce for each block, since the HMAC for a message guarantees the creator of the HMAC had the key used to create the message and the message itself, therefore creating the same HMAC for two different messages or for two different keys, or any combination thereof, should be impractical (nearly 2^numbits difficulty for the number of bits in the nonce).
Assumptions:
- Truncating an HMAC only reduces the security of the HMAC in the same way that truncating a hash reduces the security guarantees of the hash.
- Truncating SHA512 to numbits only reduces the security guarantees in that the difficulty of creating a collision is reduced to ~2^numbits from 2^512. Since the non power of 2 variants of SHA are simply truncated versions of other SHAs, that would seem to bear this out.
- A combination of message and 'secret' key is impractical to find that produces the same HMAC as a different message and/or 'secret' key.
- The impracticallity of finding an HMAC collision is on the order of 2^numbits where numbits is the bits of the hash used for the HMAC.
Does using a counter that starts from 0 provide the same security guarantees given that a different random secret key is used for each file?