0

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?

c00000fd
  • 171
  • 6
  • 1
    See [here](https://security.stackexchange.com/a/183366) for converting old hashes and [here](https://security.stackexchange.com/q/23409/151903) for using the user's password to encrypt their data. – AndrolGenhald Apr 12 '18 at 21:33
  • @AndrolGenhald: Yeah, I was thinking to do `pbkdf2(sha1(password))` as well, but the issue is that I have to encrypt the plaintext data too. In that case how would I derive the encryption key if I don't know user password? – c00000fd Apr 12 '18 at 22:20
  • 1
    You could use `pbkdf2(sha1(password))` as the encryption key and `sha256(pbkdf2(sha1(password)))` as the password hash. Of course in this case if the old hashes are ever leaked from a backup or something your encryption keys are exposed, which is one advantage of waiting for people to log in and starting from scratch instead of using an existing hash. – AndrolGenhald Apr 12 '18 at 22:36
  • @AndrolGenhald: Yeah, I'm not sure if your suggestion makes it "more secure" than just keeping it as plaintext. `pbkdf2(sha1(password))` is a trivial thing to calculate from the other column entries. So what's the point of doing it? – c00000fd Apr 12 '18 at 22:46
  • How is it trivial to calculate from other column entries? With my suggestion you shouldn't be storing `password`, `sha1(password)`, or `pbkdf2(sha1(password))` at all. – AndrolGenhald Apr 12 '18 at 22:51
  • @AndrolGenhald: `sha1(password)` is currently stored in the database. This means that anyone can calculate `pbkdf2(sha1(password))` for it to derive an encryption key. Am I missing something? – c00000fd Apr 12 '18 at 22:57
  • Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/75947/discussion-between-androlgenhald-and-c00000fd). – AndrolGenhald Apr 12 '18 at 22:59
  • 5
    Duplicate of [Migrating password db off MD5 by chaining MD5 and Bcrypt?](https://security.stackexchange.com/questions/119680), [How to replace an old password hashing method with a newer one in software?](https://security.stackexchange.com/questions/90561), [Hash function change](https://security.stackexchange.com/questions/19310/), [Is there any recommended approach for “upgrading” MD5 hashes to something secure?](https://security.stackexchange.com/questions/127298) and many others. – Steffen Ullrich Apr 13 '18 at 03:21
  • You can probably get most of the clear text by downloading a list of common password hashes. Just Google, there are lots of them. – Neil Smithline Apr 13 '18 at 03:51

1 Answers1

0

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.

ThoriumBR
  • 51,983
  • 13
  • 131
  • 149
  • 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 08:57
  • @keithRozario You definitely don't want to use a cleartext password as a key, you need to run it through password based key derivation function first. – AndrolGenhald Apr 13 '18 at 15:18
  • @AndrolGenhald you’re right, I must have missed that. Use the users password to generate the KEK. – keithRozario Apr 14 '18 at 01:55