Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

security - Back end password encryption vs hashing

I have questions regarding the best way to secure the authentication of users.

I have come across a web application that encrypts the user password in the back end. However this encryption is done with the same key to all passwords. Also, this key is "hardcoded" in the back end.

They (the app developers) claim that this is perfectly secure. However I have my doubts. I believe that this method can cause two problems:

  • The reason to encrypt passwords is to avoid access to the passwords in the event of an unauthorized database access. However if you store the key in the same server chances are they will also be able to obtain the key.

  • The same password will yield the same encrypted value therefore it will be easier to attack the system.

My questions are the following:

  • Am I right about my claims? And if it is really that insecure, should I warn them about the possible threat?

  • What would be the pros and cons of using a hash + salt approach instead?

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'm not sure if you might mistakenly mixed up encryption and hashing together. If the user's password is be encrypted and not hashed then there is potential for an attacker to steal all the user password in the event of a data breach.

There are a number of factors that you seem to be looking over when it comes to authentication. Firstly, any hashing should be done in the back-end and never in the front-end. Hashing in the front-end still leaves you vulnerable to hash attacks.

Some developers adopt a double-hash approach in which they hash the password in the front-end and then re-hash it in the back-end. I believe this is unnecessary, the front-end password should be covered by the HTTPS layer (TLS), however that is subject to discussion.

First, let's clarify two key terms before explaining how to securely store and authenticate users.

Encryption

You specify that the user's passwords are being encrypted, rather than hashed. What encryption functions do is map an input (user's password) to an output (encrypted password) in a 1-to-1 fashion, meaning that this is reversible.

This means that if the hacker gains access to the encryption key (private key), they can reverse the entire process easily.

Hashing

Instead, the user's password should be hashed on the server-side. Why? Because you can get away with comparing two hashes to check whether they match without ever storing the plain-text representation of that value.

And once again, you may be asking, "Why"? Well because hashing functions are one-way, meaning that the plain-text value cannot be reversed (well, they are very hard to), I shall not be going into to much detail.

What should I do?

The user's passwords should never be stored as plain-text in any part of the web server. Instead, you should be storing the user's hash. When the user then tries to login, you receive their plain-text password securely over HTTPS/TLS, hash it and if both hashes match, authenticate the user.

So a database table might look like so:

+--------------------------------------+
|  ID  |  Username  |   Password Hash  |       
+--------------------------------------+
|  1   | foo        | $2a$04$/JicM     |
|  2   | bar        | $2a$04$cxZWT     |
+--------------------------------------+
  • Note, the hashes are truncated BCrypt hashes with 4 rounds (AKA - Invalid)

Now let's take an example, between Alice and our server. Don't take the data too literally.

Alice sends a request to login with her credentials, which first passes through our secure transport layer:

{username: "foo", password: "bar"} -> TLS() -> ZwUlLviJjtCgc1B4DlFnK -> | Server |

Our server receives this, then uses it's certificate key to decrypt this:

ZwUlLviJjtCgc1B4DlFnK -> KEY() -> {username: "foo", password: "bar"} -> Web Application

Great! Our credentials have been passed securely, now what? Hash that password and compare against what we got in our database.

BCRYPT('bar') -> $2a$04$/JicM

if ($2a$04$/JicM == user.get_password_hash) {
    authenticate();
}
else {
    return status_code(401);
}

We have now been able to authenticate a user, storing an irreversible hash value and without ever storing the plain-text value. This should have answered your first and second question.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...