I’m building a small command line tool (mostly for fun) that is meant to store data (such as passwords or files) encrypted into a local database, with a user supplied password, pretty much the same functionallity as KeePass.
I’m looking for some review to what I’m doing to confirm I’m not leaving any security hole and I’m using known algorithms correctly or if there is too much redundancy.
It’s also important how resillient the data is against brute force.
The process is as follows:
- User provides a password and data
- Two 32 bytes key are derived from the user password (call it d_key and s_key), using PBKDF2 with a 16 bytes RNG (os urandom) salt (different salt for each key), and 10000 iterations (configurable)
Data is encrypted using AES CTR with d_key, and a signature is calculated from the ciphertext using HMAC sha512 with s_key
Both ciphertext and hmac signatures are stored in the database, along with the used salts and iteration count.
- User enters his password and id of the data he want’s to retrieve
d_key and s_key are generated using the existing stored salts and iteration count.
Data is loaded decrypted using d_key
HMAC is re-calculated from the encrypted data, using s_key and compared with the one stored to confirm data wasn’t modified and key is valid.
All good, data returned to the user.
Now my main question is, HMAC seems redundant, but seems like the only good way to check that the key is valid, otherwise a hash of the plain text data would need to be compared which would be very easy to reverse engineer / brute force.
Also, do I really need two separate keys for AES and HMAC? Even if using a salt?
Lastly, does PBKDF2 really help? Or would it be the same to simply use a hash function to derive the key? Since the key is not stored anywhere, it seems redudant as well, although I would guess that if the key is not salted and iterated brute could be easier.