Edit: removed a part of the original question; I'll break it down in a different post.
I am following @Polynomial's answer to store information in a database. Here are my requirements:
- Only the user can see their information. The server only sees scrambled data.
- Allows for easy password changes
- OK with "lost your password, lost your data"
- If possible, doesn't store a hash of the user password
- Use only one server and its own storage space
Here's what I have so far:
DB Table USER_DATA contains ([XORed key] [random IV] [encrypted secret data] [userID])
Data Entry
1. User enters (secret data) into a form.
2. User enters (user password)
3. Generate a strong (random key).
4. Encrypt (secret data) using (random key) and (random IV), as (encrypted secret data).
5. XOR hash of (random key) with hash of (user password) as (XORed key).
6. In the database, store in a new row: (XORed key),(random IV),(encrypted secret data), (userID)
Retrieve Data
1. Ask user for (user password).
2. Query database for (XORed key),(random IV),(encrypted secret data).
3. XOR hash (user password) with (XORed key) to retrieve the initial (random key)
4. Use (random key), (random IV) to decrypt (encrypted secret data).
5. Display decrypted data on screen.
I'd like to request feedback about the system above, regarding its (1) security and (2) efficiency. I would also like to get your thoughts about the following system:
Authentication
The simple way would be to store a hash of the password, authenticate against it, and create a session to allow browsing the records. Each record is decrypted and then displayed to the user. However, since the password is used to decrypt all user information, I'm trying to avoid storing its hash: I'm curious if it's even possible with only one server involved. Here is one system I thought of, but breaking it would take exactly the same effort of brute-forcing a hash:
Initial User Login
1. Ask user for (user password)
1. Create a strong (random key)
2. XOR (user password) with (random key) into (XORed key).
Store this value in the database.
3. Create a (random hash). Store in database.
4. Encrypt (random hash) with (random key) and (random IV)
as (Encrypted random hash). Store in database.
So now we have in the database: Table USER_AUTH ([XORed key] [random hash] [Encrypted random hash] [random IV] )
In subsequent logins, the password the user supplies is XORed with (XORed key) to retrieve (random key). (random key) is then used to decrypt (Encrypted random hash). If the decrypted value is the same as (random hash), then the password is correct.