I am currently working on a file encryption software that works via AES-GCM-256 and I am looking for feedback on the encryption key generation process I intend to implement.

So far, I have come up with the following process:

  1. User supplies password or key file.

Then, per file that is to be encrypted:

  1. Password/key file from (1 above) is hashed via SHA256 once.
  2. The result from SHA256 is base91-encoded and sent through scrypt (N=2^15, r=8, p=1) with a randomized 16-byte salt to derive a 32-Bit key for AES-GCM.
  3. The file is encrypted and authenticated using AES-GCM with the key from (2) using a randomized 96-bit nonce as iv.
  4. Scrypt-values (N, r, p, and salt) and the AES-GCM nonce (=iv) get stored (unencrypted) in the file header for decryption.

The program does make sure it doesn't process files larger than 2^39 - 256 Bits (size limit for AES-GCM encryption from NIST 800-38D).

Is this design flawed in any serious way?


In general, your concept looks OK to me. I do have a few remarks, though:

  1. Hashing the password before feeding it to scrypt is useless
  2. scrypt can process binary data, so there is no need for the base91 encoding step. Avoid steps that do not have a good reason
  3. Using the slow password hashing function scrypt fo every file will result in a bad performance if you want to encrypt or decrypt a lot of files. Rather create a single masterkey from the password with scrypt and then create the file depending keys using a fast KDF like HKDF.
  4. The biggest problem I can see: You are using a unique key for each file, but that is created by a random salt and not some file information. An attacker would be able to switch the content of two files (without altering it or learning the content) without you noticing it. To prohibit this, you should use some file metadata (preferable a unique file identifier like a file name/path) in the process. Either inject it into the key derivation process (using it as the salt) or authenticate it as additional data with AES-GCM.
  • 1
    $\begingroup$ (1) There's a reason for SHA256ing passwords: In my context it is vital that passwords supplied via user input and passwords supplied via key files are interchangeable. I.e. suppose a password is "Foobar" - it must not matter whether the users enters it a password or provides "Foobar" as key file content. The only way to achieve this, in my eyes, is to pre-hash passwords AS WELL as key files. Since key files get hashed in chunks, the hash function must be Merkle–Damgård-based and fast. (2) I will look into this. (4) I forgot: The filename (encrypted) IS included in the encrypted file. $\endgroup$ – FineJoe Sep 10 '18 at 12:35

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.