Password Encryption at Client side and Decryption at Server

Posted by Dhyani on 17-May-2017 01:05

Hi All,

We are having a Banking customer facing webspeed application where we require to encrypt the user password entered into login page at client (Web Browser) side and then further need to decrypt the same at server (Webspeed) side. can you please advise me the best approach to do this.

If there is anyone who has implemented such functionality in Webspeed Application , can you please share both client side and server side code for encryption decryption.

Thanks in Advance to all users !!!

Thanks,

Ajay Dhyani,  

Posted by bronco on 17-May-2017 10:03

To the OP: you could take a look at: knowledgebase.progress.com/.../P176068

This is about asymmetric encryption which avoids exchanging altogether. For the clientside stuff I would take a look at: gist.github.com/.../8619441

All Replies

Posted by Peter Judge on 17-May-2017 08:28

You should at the very least be using HTTPS for the login page submissions.
 
You should also not be using encryption for the credentials – rather use a (salted) hash (ie a one-way scrambling). Encryption means that the client needs a key and you should not be propagating your keys to browsers.

Posted by Matt Baker on 17-May-2017 08:48

Peter, occasionally a request comes up to obfuscate the password, even running on HTTPS on the client before sending it to the server.    

I assume this is so that the password remains obfuscated even when travelling through an SSL enabled proxy.

There is already an implementation that does built into web browsers:  It is called HTTP Digest authentication.  

I dislike HTTP Digest authentication because it requires the server store the unencrypted form of the password in order to generate the same hash as the client (since it uses a nonce value for each auth request as part of the hash).  Storing unencrypted passwords on the server is dangerous.  Just ask Adobe (and dozens of other high profile companies).  Passwords should never be stored as cleartext on the server.  They should be hashed and salted with multiple rounds.  

There is cheat cheat on the OWASP wiki which has a long list of items to consider when performing authentication.

www.owasp.org/.../Authentication_Cheat_Sheet

Posted by gus bjorklund on 17-May-2017 08:57

the right way to do this is to hash the cleat-text password with a cryptographic hash function (for example, with SHA-2) and keep the hashed value stored on the server side.

then, on the client side, you hash whatever the user provides as a password and send it to the server side. if the value sent matches what the server has, then the user entered the right password.

this way, the clear-text password does not have to be stored anywhere and only the user needs to know the password.

Posted by Matt Baker on 17-May-2017 08:59

Go read the Adobe disaster write up on failure to properly store hashed passwords.

nakedsecurity.sophos.com/.../

They tried this.  Someone broke into their servers and stole account data on 150 million accounts.  There was a 4GB compressed bundle of their entire account data dumped out to the public internet.

Go read the stack overflow discussion on this for additional thoughts.

security.stackexchange.com/.../https-security-should-password-be-hashed-server-side-or-client-side

You need to understand WHY they want to hash the passwords on the client side and how to do it properly.

Posted by Matt Baker on 17-May-2017 09:01

Hashing on the client and comparing the hash against what is on the server is a BAD idea.  

A hashed password going across the wire is identical to a cleartext password going over the wire.

You MUST use a nonce to do this properly.  Which means you have to store cleartext on the server...which is an even worse idea.

Don't do this.

Posted by bronco on 17-May-2017 09:31

Sorry Gus, that's definitely not a good idea.

The best way to store a hashed password, that is obvious. Key here is how do hash. Well, "standard" here is compose a hashing SALT which is based on a part which is the same for every user concatenated (or whatever means of combining) with a user specific part of the SALT which you can happily story alongside the user record. So: salt = f(generic_part, user_part). This also implies that hashing cannot be done on the client (because it's a nono to share your salts to the client).  The resulting hash is stored in the user record.

Back to the original question, I guess there's no alternative than to encrypt it on the client, decrypt on the server, hash on the server and compare that hash against the hash stored in the user record. Then you still have to exchange some sort of encryption key to make it possible to encrypt client side....

Posted by bronco on 17-May-2017 09:37

My assumption is btw that the customer of Ajay Dhyani want to prevent password theft by some sort of man in the middle attack. See (f.e.): news.netcraft.com/.../95-of-https-servers-vulnerable-to-trivial-mitm-attacks.html

Posted by bronco on 17-May-2017 10:03

To the OP: you could take a look at: knowledgebase.progress.com/.../P176068

This is about asymmetric encryption which avoids exchanging altogether. For the clientside stuff I would take a look at: gist.github.com/.../8619441

Posted by jankeir on 17-May-2017 10:05

I think you misunderstood. The salt is what is combined with the password before the hashing, not the result. In your example it would be the 'generic part'. Also, you don't want it to be generic, you want it to be different for each user. You store the salt per user and the result of the hash of pw combined with salt. The idea is that if someone steals your database they have to do a brute force against every single password, not just a single brute force that gives all passwords in the database.

There are some details here: crackstation.net/hashing-security.htm

Posted by bronco on 17-May-2017 10:39

No I didn't misunderstood :-)

The generic part is for example a GUID. You can store this in your sources (say in the generic_salt variable). The user record has a salt field (also with a GUID). Now the actual salt you use for your MESSAGE-DIGEST function is: generic_salt + user.salt (= combined_salt). That's what I meant with f().

Now the actual hashing is done with MESSAGE-DIGEST("sha-512", password, combined_salt). This way the crooks still don't have all the needed info if they steal your database. Rainbow tables are not going to work either.

Posted by jankeir on 17-May-2017 10:58

Ah sorry, I guess I misunderstood what you were saying ;-) But still, read the link, you may want a more expensive hashing algorithm ;-) It's suprising how cheap it is to brute force some hashes with a couple of GCE or EC2 nodes. Or even better with a good old botnet. Most hashing functions were designed to be cheap to calculate on purpose (you don't want a file checksum verification to take ages), but you do want one that is expensive for storing passwords.

Posted by bronco on 17-May-2017 11:11

Don't know if you misunderstood. It's probably my lousy way of writing it :-)

Concerning SHA-512, it's the best OE currently has to offer I'm afraid. The article contradicts itself btw,

"Only cryptographic hash functions may be used to implement password hashing. Hash functions like SHA256, SHA512, RipeMD, and WHIRLPOOL are cryptographic hash functions."

and further on:

"Nevertheless, it is a good idea to use a more secure hash function like SHA256, SHA512, RipeMD, or WHIRLPOOL if possible."

And in the FAQ near the end:

"DO NOT use: Fast cryptographic hash functions such as MD5, SHA1, SHA256, SHA512, RipeMD, WHIRLPOOL, SHA3, etc."

I think if you use SHA-512 you can fend of the legal sharks in case of theft :-)

Posted by Matt Baker on 17-May-2017 11:49

Hash functions have different uses.  

"fast" ones like the SHA- series are designed as a quick way to generate a hash for a largish amount of data.  Other ones like bcrypt/scrypt and so-on are designed specifically to be slow so it is troublesome to generate in large quantities to attack an authetnication mechanism.

"fast" ones are convenient as they are easy and "fast".  They may be "good enough" to use with authentication if  you use salts and multi-rounds.

Hash algorithms like bcrypt already have salt and multiple rounds built-in as it is intended for use with authentication systems.

So the "best practice" here is to use an algorithm intended for its purpose and don't cheat by abusing an algorithm for something it isn't intended for.

Posted by bronco on 17-May-2017 12:12
Posted by Dhyani on 18-May-2017 00:10

Hi Peter,

Our communication is already secured i.e. we are using https. Again for storing the password in database we are already using one-way encryption. However, to make the credential more secure and not to be stored in browser dev tool in plain text format we want to encrypt it there. Example: when we enters the password in login page press F12 in browser and check the params in Dev Tool opened after submitting the page. we can see the entered password in plain text form there. So we want to secure it there for any attack.

Thanks ,

Ajay Dhyani,

Posted by Dhyani on 18-May-2017 00:20

Yes bronco, you understand my requirement clearly. We want to secure it from any attack in case of the system hack or any other attack before reaching the password to the secured https connection.

Posted by bronco on 18-May-2017 00:27

If the requirements are that strict the customer should consider 2-factor authentication IMHO.

Posted by Dhyani on 18-May-2017 04:45

Hi Bronco,

I had done my research on it and as this requirement can be completed using any asymmetric cryptographic algorithm which is not supported by Progress. openssl is a way to implement rsa but I don't know how I can implement it in my scenario at server side. For client side i found link github.com/.../jsencrypt useful in support of openssl implementation at server side, but the problem is I don't have any idea how to implement it at server side in my case.

In my case i have to create private and public key at server side and then need to send public key to the browser and store private key at server side. In client side need to encrypt the password using public key and then need to send it to the server. Server needs to decrypt it using stored private key. Any idea for server side implementation?

Thanks,

Ajay,

Posted by Dhyani on 18-May-2017 04:48

Multi Factor authentication has already been implemented but it's include a fees for customer. This requirement is not directly from customer, it's a issue discovered by our security team and we need to implement it to follow the company security compliances.

Posted by jankeir on 18-May-2017 05:36

I think if you can't trust the browser any attempt is futile. If the attacker has acces to the password in the dom/developer tools, why would he not have the ability to capture the password while it is being typed? It doesn't matter you encrypt it before sending if the attacker has already captured while it was being typed.

If the attacker doesn't have access to the browser but somehow managed to insert a root certificate or in another way managed to create a man in the middle attack, he could easily modify the login page to take out the encryption part and do it 'in the middle' so your server doesn't notice but he still sees the password. SSL already does asymmetric cryptography, that's what it's for, if you don't trust SSL why would you trust your own algorithm (which is being passed over and only verified by SSL!) Any successful attack on SSL would be sufficient to remove whatever extra encryption you add before it is even done. Any successful attack on the browser would also be sufficient to get the password even before it is seen by your algorithm.

Posted by David Abdala on 18-May-2017 05:42

In another thread was mentioned that there is a version of OpenSSL shipped with Progress.

You need OS-COMMAND.

To generate a key pair:

OS-COMMAND('openssl genrsa -out <file path> 2048'), you can add a '-rand' parameter, replace 2048 with the key length you want. The key pair goes to the <file path>. Then extract public key with: OS-COMMAND('openssl rsa -in <file path> -out <pubkey file> -outform PEM -pubout'). That lets you with the public key in <pubkey file> and the private key in <file path>.

Look the OpenSSL help (which is horrible by the way) for the command line to use for the encryption/decryption (we do signing, and sign verification, which is similar): OS-COMMAND('openssl rsautl -verify -inkey <public key file> -keyform PEM -pubin -in <signature file>  -out <result file>') but uses public key.

Good luck.

Posted by Dhyani on 18-May-2017 07:36

Thanks David for your answer but here the main challenge I am facing is to how to decrypt the password at server side using this private key. For client side i got the rsa algorithm js file but for server side no clew yet.

Posted by Matt Baker on 18-May-2017 07:43

You need to go back to your security team and get specific requirements.  These would include what specific techniques you are going to implement, and which specific algorithms, and specifications on how to test and implement this.  

Adding another layer of "encryption" for one value in an HTML form on top of an already encrypted channel can't be solved without knowing exactly what issue the security team intends to solve.

Go ready up on the OWASP page I sent earlier, along with other techniques on the owasp.org website.  You will find the topics with answers and techniques there much more useful than here.

Posted by Dhyani on 22-May-2017 06:01

Thanks Bronco, With the help of these link I am able to implement RSA algorithm at both client side and server side.

Posted by bronco on 22-May-2017 06:32

Cool!

This thread is closed