I'm designing a small personal journal web application for my wife. I'm a crypto newb, but I want her to feel secure knowing only she will have access to her journal entries. I am thinking of the following scheme to achieve this using the Web Crypto API:
- User registers. A
masterKeyis generated and wrapped (using AES-KW) using a PBKDF2 derived key (
masterKeyWrapKey) from the user's
passwordand a random salt,
masterKeyWrapSalt. We now have
masterKeyWrapSaltis sent the server for storage. When changing passwords, we simply perform the previous steps with the new password, re-using
masterKeyinstead of generating a new one.
- User logs in. Their password is hashed (yet to determine which hash to use) on the client side and sent to the server, so that the server doesn't get to use it to derive the
masterKeyWrapKey. The hash used here must be different than the one used to generate
masterKeyWrapKey, otherwise we'll just be sending the key to unwrap
wrappedMasterKeyto the server on each log in.
- Upon successful logging in, the server sends the user's
masterKeyWrapSalt. We use PBKDF2 against
unwrapKeyand use that to unwrap
wrappedMasterKey, getting back our
- The user can now encrypt and decrypt their journal entries using their
masterKey. I am planning on using AES-256-GCM with a 96 bit random IV produced from
Crypto.getRandomValues(). Given the amount of posts there's likely to be, I don't think I need to worry about an IV collision.
It sounds pretty safe to me I'd love to hear what people in the know think. I've read that one should never implement their own encryption ANYTHING, but the temptation is strong.. especially on such a small project.
Edit to add information:
PBKDF2 was chosen as it is the only password based key derivation function available in the
Web Crypto API - I want to avoid dependence on any external crypto libraries.