This question already has an answer here:

I'm currently working on conversion of an old database format where user login passwords were stored as SHA-1 hashes. That same table also contains other user data that is stored in plaintext.

My goal now is to convert password SHA-1 hashes into PBKDF2 algorithm and then also encrypt plaintext (non-password related) data with AES-256-GCM symmetric cipher using the key derived from the result of running a user password thru PBKDF2. GCM part will also allow for authentication of user passwords & for data integrity.

So I'm trying to research how to do it correctly. Namely, do I convert these records as users try to log in? In that case some good number of entries will still remain with SHA-1 hashes for a while, if not indefinitely, which is NOT good.

So what is the recommended approach here?

marked as duplicate by Steffen Ullrich, Neil Smithline, forest, Tom K., Xander Apr 13 '18 at 20:11

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


You will have to wait the users to login to change the passwords. As soon as you validate the password, re-encrypt it with the new algorithm and save it on the database.

But don't use the user password as a key to encrypt the other user data. Doing this you will need to re-encrypt everything again every time the user changes the password. Instead, generate a secure random key, and encrypt this key with the user password. Use this key to encrypt the data. When the user changes the password, you will only have to re-encrypt the key, all other data don't have to change.

If you don't want to leave SHA1 lingering on the server forever, specify a deadline for changing (~3 months), or threshold of converted hashes (75%), and when the mark is reached, expire all SHA1 passwords and instruct those users to reset their passwords when they try to login weeks (or decades) later. This page from OWASP have a nice cheat sheet for that. Basically you identify the user (ask for username AND registered email, for example), send a unique link with an expiring token, and let the user create another password using this unique link.

  • Probably worth noting that the KEK should be derived from the password, but should not be stored as the password hash or derived from the password hash, as I'm not sure OP understands this. – AndrolGenhald Apr 12 '18 at 21:30
  • Hmm, good suggestions, Thanks. Except that leaving those SHA1s on the server doesn't seem like a reasonable idea. It may take years before they're changed, if ever. Is that the only way how it's done? – c00000fd Apr 12 '18 at 21:33
  • Or you wait the user to log in, or you bruteforce the hashes yourself and re-encrypt. – ThoriumBR Apr 12 '18 at 21:43
  • @ThoriumBR: :) I don't think I wanna do brute-forcing. ... So I'm still looking for other possibilities. – c00000fd Apr 12 '18 at 23:49
  • Not sure why this is down-voted. This seems to be the only way to do it. Generate a random encryption key to encrypt the data. Encrypt the random key with the users cleartext password -- and also store the hash of the users passwords (preferably using an algo like BCRYPT) together with salting. And since for some users you don't have the cleartext password, this is an issue. If you're unwilling to wait for users to logon, then encrypt everything with random key, encrypt random key with a 'reseted' password. And force users to reset their passwords (via email or something) – keithRozario Apr 13 '18 at 8:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.