How to generate a hash on the client side?

10

I am researching ways to create a login system with a secure encryption that does not weigh to the server. Home Taking the example this answer I'm looking for a way to do client-side encryption, thus sending the password already encrypted for php, thereby reducing processing ness. My intention is to use 'cost'=> 12 or higher for BCrypt, it will only depend on client side performance on popular machines.

However, I am open to other possibilities of cryptography that are possible on the client side.

  

As quoted by @Bacco in his response:

     

"Since hashing is purposely" expensive ", it would make sense in a client-server architecture to use the client's CPU. After all, when 100 clients connect to a single server, collectively they have much more processing power." >

    
asked by anonymous 20.02.2015 / 16:52

3 answers

9

You need something like the Secure Remote Password protocol (SRP). As pointed out by Earendul and André Ribeiro, simply moving the server hash to the client overrides all the security benefits - since an attacker who obtains a copy of the DB can simply use the stored hash to immediately log in as any user (since < strong> access credential becomes the hash, not the original password). You need a protocol whose security features hold even with the hash done on the client side.

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

It's a bit trickier than most protocols - because it involves multiple messages going back and forth between the client and the server. There are also some parameters to be set, see the referenced reference for more details.

To register a new user:

  • The client whose password is p chooses a random salt s and calculates the hash x = H(s, p) ; also calculates v = g^x , where g is a common parameter between the server and the clients.
  • The server stores v and s associated with that client's username . x is discarded - so even if an attacker copies the BD, it will not know the result of the hash.
  • For an existing user to login:

  • The client chooses a random (and ephemeral) a secret key and sends A = g^a to the server (plus your username );
  • The server also chooses an ephemeral key b , calculates B = kv + g^b ( k is a parameter calculated independently by both parties) and sends B and s to client;
  • Both compute u = H(A, B) ;
  • The client calculates Sc = (B-kg^x)^(a + ux) and K = H(Sc) , making use again of its p password to get x ;
  • Server calculates Ss = (Av^u)^b and K = H(Ss) .
  • Now both the client and the server have a shared (and ephemeral) secret key, derived in part from the user's password. It remains only each of them to prove to the other that they have reached the same result:

  • The client sends the server M1 = H(H(N) xor H(g) | H(I) | s | A | B | K) , and the server checks using its K value. | means the concatenation of strings. N is another common parameter between client and server, and I is simply the username .
  • The server sends the client M2 = H(A | M1 | K) , and the client checks using its K value.
  • Source: Wikipedia

    This is the original protocol, which uses SHA-256 as the hash. As you can see, it is used several times during the protocol, so it is unfeasible to replace it with a slow hash in all its uses - when all you want is to protect the password. One preferable option - such as pointed out by Tom Leek in security.SE - is to keep the protocol identical, 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 s2 salt - if your implementation supports it of course). Thus you gain hash protection without increasing the load on the server.

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

        
    24.02.2015 / 15:34
    3

    You can use bcryptjs .

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

    Some performance tests are worth checking to see if a cost of 12 will not be too slow for simpler machines. The bcryptjs wiki itself has a benchmark , but keep in mind that the test was performed on an Intel Core i7 -2600K.

        
    23.02.2015 / 13:57
    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 encrypted password, he can use that exact password in the future, and the server will not know if it was you or not that is sending that encrypted password. This attack is also known as Replay Attack . Of course, it is better than sending the pure password.

    To resolve this problem you can use the Nonce . Basically it works as follows:

    • Client requests a nonce (something random, some rubbish) from the server. The server sends in plaintext;
    • The client also generates a nonce , concatenates with the nonce password of the server, generates hash , and sends the server, along with your nonce in plain text.
    • The server knows your nonce and the client, and thus can decrypt the password.

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

    As you mentioned performance the above method, the server could just check the nonce of the client and check whether it was already used before or not, but for this it would have to save the nonces already used in a table. But it would prevent the server from having to decrypt the password again.

    Note: With the above method just to get the idea of how to do the client side hash, however, it requires that the server already have access to the passwords.

    In this answer the author talks about client-side performance. Briefly, it says that if, for example, hash was done in javascript, it might be as slow as the server, since javascript does not support this kind of processing, making it a slow language for this objective.

    References:

    24.02.2015 / 13:47