Monday, December 22, 2008

How does Password Encryption work in real world?

Password encryption in work: illustration using SBI Sign In process

Last week I received an email (from one of our visitors, Anil) inquiring about what all actually takes place to ensure that the password (or any other sensitive data for that matter) gets encrypted before the request is sent to the Web/App Server? Thanks Anil for raising such a nice point.

In this article, I'll try to discuss how the password encryption feature typically works. Few details might be implementation dependent and hence might be little different in your case than what is mentioned below (and in the follow-up article), but the underlying idea will probably remain the same (more or less) for most of real world applications which require authentication.

Okay, let's start from thinking about which all places do we actually need to put encryption into action and how do we implement them? Except the possible encryption done at the Database end, there are two popular approaches of implementing encryption - One, which is done at the client side (the one we will mainly talk about in this article) and Two, which is done at the server side (i.e., the request carries the actual password and at the server it's encrypted to be processed further).

The former of the two is obviously safer to have as it eliminates the risk of the request being intercepted in the middle before it actually reaches the web/app server. Well... you can say that the data packaged in a HTTP POST request is automatically encrypted in case of HTTPS, but an extra level of encryption will only add to the security of the web application. Of course, the implementation should not be too much time consuming otherwise the benefits of having a more secure application will be ruled over by the frustration it might cause to its end-users.

Though, it depends upon the actual implementation, but possibly the preferred choice (in highly secure systems) is that the actual password should not be exposed anywhere in system, which means the encrypted password stored in DB is fetched and probably not decrypted back to actual password which the end-user uses, but instead some other form which is matched with the decrypted one at the middle-tier to authenticate the user. Find below a pictorial representation of how actually such a password authentication scenario works:

authentication of user password
The entered password is first encrypted at the client side using the Public Key ('public key1' in the above diagram) and then the encrypted password reaches the App Server where it's decrypted a corresponding Private Key ('private key1' in the above diagram). App Server also fetches the password stored in the database, which might need to be decrypted using another Private Key ('private key2' in the above diagram). Now, the implementation of the algorithms and the generation of the keys should be such that both the decrypted passwords 'decryptedpwd1' and 'decryptedpwd2' should match equal for all the valid cases and they should be unequal otherwise.

How can the encryption be implemented? Will JavaScript/VBScript suffice?

Next question arises, how can we do it effectively and at the same time without consuming much time? The fastest possible way would probably be to have some mechanism in place so that the encryption can take place at the client side only. Okay, so how can the encryption take place at the client side? If we put both the encryption also definition and the public key in the JavaScript (or VBScript) code then one can easily see everything just by viewing the page source. Did you think that making the JavaScript external can solve your problem? As in you only declare the JS file in that case and not list down the contents. Well... if you did think this, you got to think again. A external JS file is equally exposed for viewing by the clients as you can simply type the path (if the path is absolute OR just append the relative path to the roor URL) in the browser window and the complete JS will be there for you to be viewed. We'll see examples below. Evidently, the encryption won't really carry any benefit here.

How else can we do it at the client side? How good would Applets be?

Yeah... now you got a better way of handling the situation. As we all know that applets are also downloaded to the client machine and are executed at client machine itself, so we can now make use of the Java programming language and its security mechanism for having the encryption implemented in a far better manner. What's probably an even more appealing about this approach is that you can NOT see the source of the applet class(es) directly. They are normally shipped in JAR bundles which gives an extra layer of security. You can claim that since the JARs are downloaded and the .class file of the applet class runs within the vicinity of the client JVM so the bytecodes would certainly be available which can then be de-compiled to have a look at the source. Yeah, you're are right that the bytecodes are available at the client machine and it can be decompiled. But, what makes this approach better than the JavaScript approach can be understood by following points:

  • Bytecode tempering is automatically detected: if an intruder somehow gets hold of the bytecodes and changes that, the changed bytecode will throw an exception while running whereas any such changes in the JavaScript (or VBSCript) source won't be detected.
  • Security Mechanism of Java is much more versatile: what we talked about in the above point is also an integral part of the Java Security mechanism, but it's not only limited to this. It's quite versatile and layered. No such benefit is available with JavaScript (or VBScript).
  • JVM offers a far more consistent environment: bytecodes run within a Java Virtual Machine which obviously offers a far more consistent and stable environment as compared to the environment in which JavaScript (or VBSCript) code runs.
  • Impl of different public/private keys for every new request: you would probably be aware of the Secure Key concept which forms a part of the password on many systems. The underlying idea in such implementations is to have part of the password which keeps on changing on a continuous basis and thus making it virtually impossible for the attackers to guess that. Similarly, if we want to step up the encryption strength to an even higher level, we can put in place different public/private key combinations for every new request.

Now that we have understood the underlying concept of password encryption, let's move on and see a pictorial representation of how password encryption has been implemented in a real world live scenario. We'll take example of SBI Net Banking and try to understand how the user entered password is getting encrypted there - Diagrammatic representation of Password Encryption >>

Liked the article? You may like to Subscribe to this blog for regular updates. You may also like to follow the blog to manage the bookmark easily and to tell the world that you enjoy GeekExplains. You can find the 'Followers' widget in the rightmost sidebar.



Anil said...

Hi Geek
thanx for giving good solution for client level login security.

amit said...

Its one of the best article in terms of security testing

Anonymous said...

ACK! Don't encrypt passwords. People rarely, if ever, get key management right and your database of passwords could be recovered. It's better to just use a cryptographically strong hash algorithm. Take the password, convert to bytes, generate a random salt, hash the 2 and store them.
The next time a user logs in, pull the hash and the salt out, re-hash the password they just entered with the salt and see if the matches the stored value. Much easier and it's not reversible!

Geek said...

Agreed, Dave. That's what normally used mainly because (as you said) that approach is much easier. Though, the encryption also works the similar way, but one of course needs to have key management rights to implement this. The random salt of the hashing approach works as the key in the encryption approach - kind of having only one key instead having a pair of public-private keys. A pair of keys in case of encryption probably makes the mechanism stronger, but the implementation will certainly be much more complex.

The intention of this article was not to suggest that one should go for this approach. It was just an attempt to discuss how the client-side encryption works in real-world applications.

The hashing approach coupled with SSL (using HTTPS) will probably be good enough in most of the cases, but then there are apps using the encryption approach as well. I believe not all of them are doing this unintentionally :-)

Thank you for taking your time out and posting such a thoughtful comment. This will certainly add value to the quality of the article. Hope you'll keep contributing!