My goal is to design an encryption scheme for the application so that the backend stores encrypted data and the whole process of encoding and decoding happens on the frontend. And you can be sure that even if the backend database gets compromised the data is impossible to decrypt.
I'm in no way an expert on the topic but tried my best to grasp as much information as I could in the last couple of weeks. It's obviously not as easy as just doing the plain encryption of the data via master password from the user since it could be prone to KPA and rainbow tables.
For the purpose of this particular question to not make it too broad assume that the passwords that are being used are strong enough (e.g. 16+ characters including lower/uppercase, special symbols, etc). As well as the user device is not compromised in any way. So we talking only about the storage part of the encrypted data.
The scheme I came up with is:
- User has its master password
- When we need to encrypt something:
- We generate a random salt value
- Use Argon to derive a key from the master password and salt value from the previous step.
- Using the key from the previous step we encrypt the data with AES256 and send it over to the backend along with the salt used where it is stored.
- When we need to decrypt something:
- We do the same steps to get the key and decrypt the data to show it.
If I understood everything correctly the output for the encryption key should be consistent so that we can decrypt the info from anywhere.
Did I miss something? What attacks I haven't thought about?
EDIT1:
Users can choose both the pin and the master password. The idea I thought about is that if the salt could be generated from the pin consistently then this whole process could be done for example on a new user device and with the knowledge of both he could decrypt previous info, that way if the database gets compromised - the attacker won't know the salt that was used making it harder to decrypt.
EDIT2: Updated information in the question based on comments and an answer.
EDIT3: To increase security I could create a pepper key from the user's pin code (separate value, not related to the master password), but still apply random salt during encryption before sending it to the backend.
Based on the answers I'll use: Argon2 for key derivation from the master password, a random salt value for each derivation of not less than 128 bits, AES256-GCM
for encryption, and optionally implement the pepper via key derivation from pin code.
Thanks to everybody!