How do I generate a hash in the client-side?

Asked

Viewed 828 times

11

I’m researching ways to create a login system with a secure encryption that doesn’t weigh down the server.
Taking as an example that answer I am searching for a way to make client-side encryption, thus sending the already encrypted password to php, thus reducing the processing need. My intention is to use 'cost'=> 12 or higher for Bcrypt, it will only depend on the performance on the client-side on popular machines.

But I am open to other cryptographic possibilities that are possible on the client side.

As quoted by @Bacco in his reply:

"Because hashing is purposely "expensive", it would make sense for a client-server architecture to use the client’s CPU. After all, when 100 clients connect to one server, collectively they have much more processing power."

  • 5

    Perhaps it is more advantage to use SSL (HTTPS) than to implement all this on the client side. Sending the hash to the server will be basically the same thing as sending the password. If someone intercepts this hash, all they need to do is resend the hash to authenticate.

  • @Andréribeiro If I understand your placement correctly, I think you are mistaken, because the password verification is based on the original password, typed by the user. What Rodrigo wants, I believe, would only generate the hash when registering the password. But I could be wrong, because it was not specified if it is for the login or registration...

  • @Andréribeiro is right, no matter if an access credential is a "password", "key", "hash" or anything else - if presenting that to the server authenticates you, then the attacker only has to get hold of that to gain access to your account. The defense (i.e. the slow hash) then has to be applied to that in order to keep the original credential out of the BD.

3 answers

10


You need something like Secure Remote Password Protocol (SRP). As pointed out by Earendul and André Ribeiro, simply moving the server hash pro client negates all security benefits - because an attacker who obtains a copy of the BD can simply use the stored hash to log in immediately as any user (since the access pass becomes the hash, not the original password). Requires a protocol whose security features remain even with the hash on the client side.

And that protocol is SRP. The original protocol has a weakness (weakness that remains present in the standard SRP implementation via SSL/TLS), which is the use of a simple SHA-256 as a hash function, rather than a slow function like Bcrypt. So you would have to implement yourself in the application layer and/or get a secure implementation in the same way.

It’s a little bit more complicated than most protocols - because it involves multiple messages coming and going between the client and the server. There are also some parameters to be established, see the indicated reference for more details.

To register a new user:

  1. The customer whose password is p, choose a random salt s and calculates the hash x = H(s, p); calculates also v = g^x, where g is a common parameter between the server and the clients.
  2. The server stores v and s associated with username of that client. x is discarded - so that even if an attacker copies the BD, he will not know the result of the hash.

For an existing user to log in:

  1. The client chooses a secret key a random (and ephemeral) and sends A = g^a to the server (plus your username);
  2. The server also chooses an ephemeral key b, calculates B = kv + g^b (k is a parameter independently calculated by both parties) and sends B and s for the client;
  3. Both calculate u = H(A, B);
  4. The customer calculates Sc = (B-kg^x)^(a + ux) and K = H(Sc), making use of your password again p to obtain x;
  5. The server calculates Ss = (Av^u)^b and K = H(Ss).

Now both the client and the server have a secret and shared key (and ephemeral), derived in part from the user’s password. It remains only for each of them to prove to the other that they have achieved the same result:

  1. Client sends to server M1 = H(H(N) xor H(g) | H(I) | s | A | B | K), and the server checks using its K. | means the concatenation of strings. N is another common parameter between client and server, and I is simply the username.
  2. Server sends to client M2 = H(A | M1 | K), and the customer checks using its K.

Source: Wikipedia

This is the original protocol, which uses SHA-256 as a hash. As you can see, it is used several times during the protocol, so that it is impossible to replace it with a slow hash in all its uses - when all you want is to protect the password. A preferable option - as pointed out by Tom Leek no security.SE - is to maintain the identical protocol, only apply p = BCrypt(s, p) in the password before using it (you can use the same salt s, but if feasible it is preferable to use a salt s2 - if your implementation gives support of course). Thus you gain the hash protection without increasing the server load.

An attacker who gains access to the comic will only see s and v = g^x, so that he would have to compute x to be able to log into the server ("simulating" the protocol offline). And how to get in x he would have to redo the hash slow, the protection of it is ensured.

  • @Rodrigoborth So the entire protocol uses a fast (and therefore cheap) hash, only the password is enhanced by the slow hash. And this reinforcement is done on the client side only, the server only sees a parameter derived from the password (the v) - which alone cannot be used to recover the original password, not without redoing the hash. In other words, the knowledge of v does not help the attacker to log in, he actually needs to x. Like x is not stored anywhere, the only way to get it is to redo the hash of p, hence the protection afforded to himself on the client side.

  • Unfortunately, no... Client side, that library for example should serve, but it would be necessary to implement the server side in your language of choice. An example server is given, pro Django, but adapting it to other platforms can be a bit tricky, yes. Do you really need this? Is there a system where the number of users logging in simultaneously is weighing on the server? I like the idea a lot, but never got to use in practice, for sheer lack of need...

  • See also TLS-SRP, the implementation of SRP directly in the transport layer. I don’t know which browsers support it, but Openssl 1.0.1 or higher already does. The only problem is to adapt it to make a strong hash on the client side, I don’t know where things stand, but this is a general concern, I believe that very soon this will be taken into account by the implementers, without us having to do any of this ourselves.

  • I wanted to see him come into the security sector of a medium-sized T.I company and say he’ll put the encryption on the client’s side and on top of that, off the https. Need to reinvent the wheel when SSL already solves the problem and still gives you time to focus on what really matters, application development. This question seems to me like one I saw in GUJ that the user said he wanted to make a system where each user registered in the system would have a proper table in the system instead of using a table of users.

  • @wryel SSL is about the transportation of the password, while hashing treats of storage. In addition, passwords themselves are protective data because people routinely (and improperly) reuse passwords or variants of passwords in several different places. It’s very bad for a company to have its customers' passwords stolen, and it happens to companies of any size. If moving the client-side encryption allows reinforcing the security of passwords at a much higher level than is possible on the server-side, then it is something quite desirable yes, since done right is clear.

  • @mgibsonbr, your explanation answers his question, but leaving open the possibility of other answers. I don’t see SSL as a password transport, but as a secure channel. If we think of other possibilities, maybe this method would still be vulnerable to MITM. This is a very long subject and there will always be pros & cons.

  • @wryel I agree, when I said "password transport" I meant data transportation in general, inclusive but not limited to passwords - that is, secure channel. As for Mitm, this protocol was designed to be resistant to this type of attack - unless the attacker was present on the initial connection (i.e. when the user creates his account), he could not run a Mitm on subsequent connections, or the protocol would fail. Anyway, being SRP something new and relatively little used, it is good to be cautious.

  • @Rodrigoborth It may be necessary for a moderator to help with this, because I don’t know which comments are constructive or not (I see most of them as pertinent to the subject). Now I’m a little out of time, but then I can move what I consider relevant to the answer itself and delete from the comments. P.S. I will remove this comment soon.

Show 4 more comments

3

Coding the password on the client side and sending it to the server will not give you much more security. If an intruder captures this coded password he may use exactly this password in the future, and the server will have no way of knowing whether or not you are sending this coded password. This attack is also known as Replay Attack. Of course it’s better than sending the pure password.

To solve this problem you can use the Nonce. Basically it works like this:

  • Customer requests a nonce (random, random junk) from the server. The server sends in plain text;
  • The customer also generates a nonce any, concatenates with the password and the nonce of the server, generates a hash of all this and send it to the server, along with your nonce plain text.
  • The server knows your nonce and the client, and so can decrypt the password.

In a similar way one can use Timestamp to achieve the same goal as nonces.

As you mentioned the above method performance, the server could just check the nonce of the customer and check whether it has been used before or not, but for that he would have to keep the nonces already used in a table. But it would avoid the server having to decrypt the password again.

Obs.: With the above method only to pass the idea of how to hash the client-side, however it requires the server to already have access to passwords.

In that reply the author talks about the performance of the client side. Briefly he says that if, for example, the hash in javascript, maybe it was as slow as the server, because javascript does not support this type of processing, making it a slow language for this purpose.

References:

  • "The server knows your nonce and the client, and so can decrypt the password" How, if for that he would need the original password of the user? (to redo the hash) While the first linked answer is accepted and well-voted, it is responding to a different question - how to secure the conveyance password - and, to be valid/feasible, assume that the server stores passwords in plain text or similar. The purpose of the third link is also another, incidentally he says: "You should still hash the password Again on the server side before".

  • Yes. I put the links only as a reference to the nonce algorithm, as a way to create the client-side hash.

3

You can use the bcryptjs.

var bcrypt = dcodeIO.bcrypt;
var hash = bcrypt.hashSync('password', 12);

It is worth performing some performance tests to verify that a cost of 12 will not be too slow for simpler machines. The bcryptjs wiki itself has a benchmark, but remember that the test was carried out on an Intel Core i7-2600K.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.