I'm reworking a website in Rails using Devise for authentication. The previous website works with a database of users with md5 passwords, and therefore I want to migrate this passwords to the encryption that Devise using. How do I solve it?
With MD5, assuming the servers can handle it, a user could very rapidly attempt to brute-force passwords just by trying lots of passwords in quick succession. bcrypt's slowness guarantees that such an attempt will be much slower. Second, a key security concept in computing is defense in depth.
A lot of your research is correct and still applies in 2021, so it is still secure to use BCrypt (which usually generates its own random salt for each password). Good password hashing algorithms are Argon2, SCrypt and BCrypt, they all offer a cost factor which controls the necessary time.
The takeaway is this: bcrypt is a secure algorithm but remember that it caps passwords at 72 bytes. You can either check if the passwords are the proper size, or opt to switch to argon2, where you'll have to set a password size limit.
The technology in the Bcrypt algorithm and process limits attacks and makes it harder for attackers to compromise passwords. Bcrypt was not designed for encrypting large amounts of data. It is best implemented for passwords, however SHA-256 is better for large amounts of data because it is less costly and faster.
Oleksi and josnidhin did a great job at answering your question. I just wanted to add some ideas what to do during the transition phase:
Migrate the DB towards having two "password hash" columns, one containing the existing old MD5 hashes, and another one for the new bcrypt hashes, initially all filled with NULL. The next time a user logs in, you do these steps:
1) Check if there's already a value in the bcrypt column. If so continue with 3., otherwise with 2.
2) Authenticate the user with the old MD5 mechanism using the value from the MD5 column. If successful, additionally compute the new bcrypt hash and store it in the new column. Done.
3) Authenticate the user using the brypt value. Simply ignore the MD5 value.
Then from time to time, check whether the new bcrypt column is filled. If so, discard the MD5 column and update your app to only use the new mechanism.
But that's wishful thinking, there are always some users that haven't logged in in the meantime. Send them a mail telling them what you are doing, that it's for their best and ask them kindly to log in soon.
After a couple of weeks, check the bcrypt status again. If there's still some passwords missing (there will be :)), what you could do is to just reset the passwords of these users, generate a random one and informing them via mail, much like what you would do if they forgot their passwords.
Then, you can finally purge the MD5 column, discard the corresponding code and upgrade your app to only use the new authentication.
I have an alternative solution:
plain text->md5->bcrypt
.This way all passwords can be migrated at once and MD5 hashes discarded permanently. Considering doing this myself, can't pick any faults with this idea. Any takers? Am I missing something obvious?
There is no way to convert an md5 hash into another kind of hash. You will have to make users log in using the old system, and then hash the password they give using the new method. Once you have the new hash, you can delete the old, md5 hash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With