Is MD5 still considered secure for single use auth

2019-06-13 15:59发布

问题:

Everyone is shooting down MD5 these days for its issues in the context of storing passwords. But what about uses where I just want to add a layer of authentication to something that will likely be used once?

This is just a hypothetical example, but let's say I have a feature to allow a user to reset their password. I email the user a link that they can click to set a new (randomly-generated) password.

My current thinking is that I'll generate an MD5 hash, using a private salt value, and a couple of identifying variables, and use that to create the link.

Let's say the salt for this feature is "8b769a378411b705" (I use the same salt for all reset password requests). The other identifying pieces of data are the user ID and a database ID of the already-generated password hashes.

salt = "8b769a378411b705" (private)
user_id = 123
pw_id = 456
code = md5(salt + " " + user_id + " " + pw_id)

which becomes

code = "692a71cd7da194145be209e40fcd3e92"

example link: confirm_reset_password.php?user_id=123&pw_id=456&code=692a71cd7da194145be209e40fcd3e92

Is this considered safe, in light of the issues with MD5? Is there another one-way hash I should consider using, like SHA-1?

I've been using PBKDF2 with SHA1 for storing passwords, and I understand that part of its benefit is in its "slowness" and how long it takes to generate hashes. I could generate those higher-quality hashes for purposes like this, but I think it can backfire, since you could easily bring a server to its knees by bombarding it with (incorrect) requests, since each one results in a significant CPU job to generate the hash (especially since I am using lots of iterations). It seems that having a "fast" algorithm is good for single use purposes, but I'm wondering if MD5 is still the best choice.

Thanks!

回答1:

First of all MD5 is considered insecure for many reasons, first of all, rainbow tables for md5 are enormous by now, and probably cover most of the hash space. Second, there are known attacks that allow you to create hash collisions (to disguise other data in the manner which will produce the same md5 output). Third its 128bits, for today its short.

Now back to your question, if you are not hosting any security-critical app, you do not store any private data, medical data, or any other "country law controlled" data, you are good with md5. Going into your algorithm, it's not insecure, but it's not super secure either, its your choice. Only thing you should add is freshness, that is some sort of timestamp telling you the validity period of your message. Secondly, your algorithm does not offer a replay protection :), if user will use this link once and leave it in browser, attacker may use this link again to reset this password. It's pretty serious flaw. So you might want to fix it.

But I want to tell you some other thing. DO NOT USE CRYPTO IF IT IS NOT ABSOLUTELY NECESSARY! My humble request. Your password resetting scheme can be easily implemented without crypto and with replay protection, and far more security. All you need to do is add an additional columns to your table "pw_reset_hash" and "reset_validity", and populate them with RANDOM number, and valid date. Issue a user a random number, and clear the fields after it's used, check for validity beforehand. And voila :) Since it's random its probably more secure than any hashing algorithm. But use a secure PRNG.



回答2:

Why base the passwordlink on something? That will only make it less secure (since its based on some known data which might leak)! In this case a randomly generated code is much better.