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
5. [file header/metadata] ciphertext
6. [file content] ciphertext
Encryption scheme:
- $hmacSalt, keySalt, iv := CSPRNG(...)$ where each value is separately assigned
- $derivedKey := scrypt(key, keySalt)$ where $key$ resembles the master keyphrase, provided by the user
- $C := E(derivedKey, iv, 5 || 6)$ where $5$ and $6$ refer to the lines denoted in my file format design
- $hmac := hmac(scrypt(key, hmacSalt), 2 || 3 || 4 || C)$
Decryption scheme:
- $derivedKey := scrypt(key, keySalt)$
- $compare(hmac, hmac(scrypt(key, hmacSalt), C))$ where $C$ refers to complete file content, with the HMAC's size as offset
- $P := D(derivedKey, iv, C)$ where $C$ is the ciphertext (which is composed of $5$ and $6$)
- Parse file header and content
The encryption cipher is AES-256 and HMAC's underlying hash is SHA2.
My questions:
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.
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?
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?
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?
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.