So this is probably a stupid question, but I'm trying to understand why the following isn't done for at-rest files encrypted via password:
- generate an AES-256 key/salt/iv
- take the plaintext message (say a 50MB file) and encrypt it with credentials from step 1
- append credentials to encrypted message
- let the user choose a password and convert it into an AES-256 key using some standard method
- encrypt results of step 3 using key from step 4, using AES as a synchronous stream cipher with a modified form of output feedback mode where:
- instead of using the plaintext to feed into the next block, a high-memory hashing function (such as Argon2i) is applied to the plaintext, and the results of that operation are fed into the next block
- said hashing function would use consistent cost parameters derived from the size of the data in 3. (and hence the number of blocks needed), plus a desired amount of memory needed to decrypt the entire file (so your encryption program knows you want it to require writing a total of 1GB of memory to decrypt this file)
Unless AES-256 itself was compromised, it would seem that to attack this file, you'd have to:
- choose a likely password and convert to the corresponding AES-256 key
- use this key to decrypt the entire file, at each block computing the Argon2i hash of the previous block (which requires a pre-determined amount of memory)
- when you reached the end of the file, use the bits at the end (which might be the key you need) to decrypt the (already decrypted once) first block and see if you're correct
Since you couldn't easily parallelize cracking due to the synchronous stream cipher (each attempt requires full-message decryption), plus the fact that each block requires you to write an arbitrary amount of memory (reducing the threat of fast GPUs/future quantum computers/etc), wouldn't a method like this provide additional security in a way that switching from AES-256 to a theoretical AES-512 would not (since each relatively short password will still generate a full AES-512 key, and you can check to see if that guess is correct without decrypting the whole message, so there's really nothing gained).
By adjusting the parameters to your hashing function (based on the size of the file), you should be able to say "attempting to decrypt this 1KB file will require writing 500MB of memory... and attempting to decrypt this 3GB file will also require writing 500MB of memory". So it wouldn't necessarily be prohibitively slow for large files.
I know there's got to be a reason this isn't done, and would love to figure out where I'm going wrong!