Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hashing user password for client / server application

I have an iPhone App communicating with a web server. When starting the App the user must authenticate with a user name and password. The communication between the App and the web server is secured (HTTPS) but I don't want to send to the web server the clear password, I would like to send just the "signature" of the password (the signature will be stored in the database on the web server).

What is the best solution to create this "signature" on IOS? Should I use MD5 or something else?

Do I need to get an external library to build this signature or can it be done using SecKeyEncrypt from IOS SDK?

In the long term I will have an App running on Android and I must be able to generate the same signature for IOS and Android.

Thanks for your help,

Sébastien.

like image 402
sebastien Avatar asked Oct 17 '13 20:10

sebastien


2 Answers

Transmitting the password in clear text is bad, so doing anything is a good first step. If you're going to make the effort, it is worth knowing how to do it right.

While MD5 is not a strong hashing algorithm anymore, choosing between MD5 and SHA256 (or even SHA512) is less important than how you use it. Let's ignore the specifics of the hashing algorithm and look at how it can be used first.

The idea of using a hash is that the hash of a string is always the same and is a one-way operation. By capturing the string, it is not supposed to be possible (or practical) to determine the password. That has become untrue in recent years with the mass use of rainbow tables. A rainbow table contains every possible password (up to a given length) and their hash, so that the attacker can use a reverse lookup to discover the password. Rainbow tables are readily available for all hash algorithms for passwords under 16 characters.

There are a few common solutions to this problem. One is to perform the hash many (around 1,000) times. The exact number of times must be known and predetermined by both the client and server so they can do it the same. This has the advantage and disadvantage of making hash generation expensive. It becomes computationally more difficult for an attacker to brute force, but rainbow tables are still useful if they are expanded to be large enough.

A better, but less common, solution is to add a known random string (commonly referred to as a Salt) to the password to make it long (maybe 64 characters). This salt must be known by both client and server in advance. This solution is cheap and easy, and it doesn't even matter if the salt is leaked out.

There is another common problem with password hashing. If a malicious user knows the hash of a user's password, that is as good as knowing the password itself for a poorly designed system. Let's assume we have an RPC function that requires a username and password hash. A malicious user that knows the password hash can submit it, even without knowing the password, and get access into the system. This known password hash will continue to work until the user changes their password, which could be months or years. What is needed is a way to limit the duration that the password hash is useful. That is achieved by using a dynamic salt.

The authentication then becomes a multi-step process.

  1. The client connects to the server and presents some sort of client (or device) identifier, such as a UUID.
  2. The server then generates a dynamic salt for that client identifier. The dynamic salt is only good for a short period of time (generally minutes to hours).
  3. The server stores the dynamic salt, its expiration, and the associated client identifier in a database table for future use.
  4. The server returns the dynamic salt back to the client, along with its expiration.
  5. The client hashes the password, using either of the two mechanisms above, concatenates the dynamic salt, hashes again, and then attempts to authenticate by using username, client identifier, and dynamically-salted hash.
  6. The server validates the submitted credentials by checking the users known password hash against the submitted value trying to concatenate and hash each known dynamic salt for that client identifier. If a match is found, authentication is accepted.

This is (roughly) the mechanism that is used by MySQL. It is secure enough that it can be used without SSL safely, but I would always recommend using SSL so that the rest of the payload is protected.

If you use secure mechanisms like this, it doesn't matter much if you use MD5 or a SHA variant. That said, it wouldn't make sense for any new development to not use SHA256, unless there was a very good reason MD5 was necessary.

like image 72
Holly Avatar answered Oct 19 '22 21:10

Holly


md5 is not the best idea - there are lots of really fast rainbow tables nowdays to decrypt them.

I would suggest using AES256 - on iOS you have NSData+CommonCrypto which allows you to easily do that.

NSString* encryptionPass = @"myEncryptionPass";
NSData* passData = [userPassword dataUsingEncoding:NSStringEncodingConversionAllowLossy];
NSError* error = nil;
NSData* encryptedPassData = [passData AES256EncryptedDataUsingKey:encryptionPass error:&error];
if(!error)
{
     NSString* encryptedString = [[NSString alloc] initWithData:encryptedPassData encoding:NSUTF8StringEncoding]
}
like image 28
Grzegorz Krukowski Avatar answered Oct 19 '22 21:10

Grzegorz Krukowski