# Single-purpose symmetric encryption scheme for single files

I'm writing a simple password manager program that will encrypt/decrypt a single file (it's size will most likely stay under a few K). This is my initial file format design:

1. hmac                        plaintext
2. hmacSalt                    plaintext
3. keySalt                     plaintext
4. iv                          plaintext
6. [file content]              ciphertext


Encryption scheme:

1. $hmacSalt, keySalt, iv := CSPRNG(...)$ where each value is separately assigned
2. $derivedKey := scrypt(key, keySalt)$ where $key$ resembles the master keyphrase, provided by the user
3. $C := E(derivedKey, iv, 5 || 6)$ where $5$ and $6$ refer to the lines denoted in my file format design
4. $hmac := hmac(scrypt(key, hmacSalt), 2 || 3 || 4 || C)$

Decryption scheme:

1. $derivedKey := scrypt(key, keySalt)$
2. $compare(hmac, hmac(scrypt(key, hmacSalt), C))$ where $C$ refers to complete file content, with the HMAC's size as offset
3. $P := D(derivedKey, iv, C)$ where $C$ is the ciphertext (which is composed of $5$ and $6$)
4. Parse file header and content

The encryption cipher is AES-256 and HMAC's underlying hash is SHA2.

My questions:

1. As you can make up from this encryption scheme, I'm using the encrypt-then-authenticate approach to enforce ciphertext integrity. In step 2 of the decryption process I perform this authentication step. If the calculated HMAC turns out to be equal to the HMAC in the file, does this mean, apart from the implied ciphertext integrity, that the supplied passphrase is certainly the same as the original passphrase used for the encryption, resulting in this ciphertext? Or should I perhaps use an additional plaintext HMAC, stored in the encrypted file header, to ensure passphrase validity.

2. I'm unsure which cipher mode of operation would be most suitable for this kind of encryption. I couldn't find much information about this, as most recommendations are based on network-based cryptography. CBC and CTR both seem good options, and I believe the security difference are negligible, as long as the implementation is done correctly. In Cryptography Engineering, the authors used to recommended CTR, but now prefer CBC as it's easier to "get right". CTR seems more susceptible to a poorly generated IV, as it's essentially a stream cipher. Which one would you recommend?

3. This question partially depends on my choice of cipher mode (question 2). Does generating a new salt and IV for each file mutation really offer a noticeable security benefit? This may sound like a stupid question, but file mutations only take place sporadically, and thus a sufficiently large IV should deter any ciphertext attacks?

4. According to the Horton Principle, the MAC should "Authenticate what is being meant, not what is being said". I understand this includes the structure of the file etc., but would including salts and IV be wise as well?

5. In my design I'm using the same underlying key as input for the encryption and HMAC function. Does the use of two separate salts offer any security benefit, or is reusing the same key inherently insecure anyway?

PS: I couldn't decide if this question would be more suited for security.stackexchange.com or not, so please forgive me if that's the case.

-
What is the advantage over `openssl enc -aes-128-gcm -in infile -out outfile -k password? – Stephen Touset Mar 30 '13 at 7:15
@StephenTouset proper key derivation? – dchest Mar 30 '13 at 9:16
Have you seen the file format of scrypt utility? It's a good reference on how to do it properly: code.google.com/p/scrypt/source/browse/trunk/FORMAT – dchest Mar 30 '13 at 9:18
@dchest scrypt's file format example seems like a good starting point, thanks! – tman Mar 30 '13 at 13:18
As far as I can see, you're not using a work factor. $\:$ – Ricky Demer Mar 30 '13 at 21:20

1. As you can make up from this encryption scheme, I'm using the encrypt-then-authenticate approach to enforce ciphertext integrity. In step 2 of the decryption process I perform this authentication step. If the calculated HMAC turns out to be equal to the HMAC in the file, does this mean, apart from the implied ciphertext integrity, that the supplied passphrase is certainly the same as the original passphrase used for the encryption, resulting in this ciphertext? Or should I perhaps use an additional plaintext HMAC, stored in the encrypted file header, to ensure passphrase validity.

If the HMAC verification of the ciphertext checks out, then you can be assured that the password is the same. Of course HMAC (and any hash algorithm) has many collisions (i.e. lots of inputs that map to the same output), but the chance that you will run into one of these in a real-world scenario with decent-sized hash are near infinitesimal. A common practice is to put a checksum (e.g. CRC32) on the plaintext to ensure that the decryption happened properly. If you want to guard against decryption errors (usually not necessary unless you have a "can't fail" super-sensitive system), then you can add such a plaintext checksum.

1. I'm unsure which cipher mode of operation would be most suitable for this kind of encryption. I couldn't find much information about this, as most recommendations are based on network-based cryptography. CBC and CTR both seem good options, and I believe the security difference are negligible, as long as the implementation is done correctly. In Cryptography Engineering, the authors used to recommended CTR, but now prefer CBC as it's easier to "get right". CTR seems more susceptible to a poorly generated IV, as it's essentially a stream cipher. Which one would you recommend?

In your scenario, since you are doing encrypt-then-sign, the mode doesn't matter so much. CTR (a stream mode) and CBC (a block mode) have different error propagation properties, different attacks, but these are somewhat irrelevant because of the pre-decrypt verification that you are doing. In my experience, CBC is more robust in more situations while CTR tends to be more flexible, but it doesn't matter for you. Go with CBC if you like. It's more important to ensure that you get a unique IV for each encryption operation.

1. This question partially depends on my choice of cipher mode (question 2). Does generating a new salt and IV for each file mutation really offer a noticeable security benefit? This may sound like a stupid question, but file mutations only take place sporadically, and thus a sufficiently large IV should deter any ciphertext attacks?

You absolutely must use a different IV for each password encryption operation. There are attacks that can be mounted against either mode if you fail to use a different IV. If you do this, then there is no need for the salts. Unique-per-password salts are used when encrypting or hashing individual passwords separately and help resist rainbow table and similar attacks. Since you are encrypting and entire file at once, I'd recommend skipping the salt and just ensuring that you use a unique IV per encryption (i.e. each time you change the file, or encrypted contents in your lines 5 and 6).

1. According to the Horton Principle, the MAC should "Authenticate what is being meant, not what is being said". I understand this includes the structure of the file etc., but would including salts and IV be wise as well?

As I said previously, no need for salts. However, it is common practice to authenticate (MAC, in your case) the modification-sensitive portions of the plaintext header. So if you had fields for version number, date, owner, etc, then you should concatenate those fields with your ciphertext and MAC the whole thing together. You don't show anything like that above, but perhaps you should consider adding such fields for other security reasons. Technically the IV is not modification-sensitive, but since you don't have a checksum on the plaintext, then it might be good idea to MAC the fields: 4 (IV) || 5 || 6.

1. In my design I'm using the same underlying key as input for the encryption and HMAC function. Does the use of two separate salts offer any security benefit, or is reusing the same key inherently insecure anyway?

Again, neither salt is needed in this implementation. HMAC (with a good underlying SHA like SHA256 or SHA512) and AES do not have practical cryptanalytic attacks and I don't know of any attack that can exploit either one if you were to use the same key for both, but this is generally considered bad practice. Instead, just make 2 keys. Or use a key derivation function (see NIST SP 800-108) to derive 2 keys from a single source of entropy/password.

Someone else already mentioned it, but is there a reason that you are using AES-CBC + HMAC instead of just AES-GCM? AES-GCM is an authenticated, encrypted mode of AES and the authentication tag is over the ciphertext. There are some nuances that you need to be aware of before using this mode, but it could be a simpler implementation for you. Otherwise, AES + HMAC is fine and fairly widely used as well.

-