Hashing a user password for a client-server application

I have an iPhone application communicating with a web server. When the application starts, the user must authenticate with the username and password. The connection between the application and the web server is secure (HTTPS), but I do not want to send a clear password to the web server, I would like to send only the "signature" of the password (the signature will be saved in the database on the web server).

What is the best solution to create this “signature” in iOS? Should I use MD5 or something else?

Do I need to get an external library to create this signature, or can it be done using SecKeyEncrypt from the iOS SDK?

In the long run, I will have an application running on Android, and I should be able to generate the same signature for iOS and Android.

Thank you for your help,

Sebastien.

+6
source share
2 answers

Passing a password in clear text is bad, so doing something is a good first step. If you are going to make an effort, it is worth knowing how to do it right.

Although MD5 is no longer a powerful hashing algorithm, choosing between MD5 and SHA256 (or even SHA512) is less important than how you use it. Let them ignore the specifics of the hashing algorithm and see how it can be used in the first place.

The idea of ​​using a hash is that the hash of a string is always the same, and a one-way operation. When capturing a string, it is not necessary (or practical) to define a password. In recent years, this has become untrue with the massive use of rainbow tables. The rainbow table contains all possible passwords (up to a certain length) and their hash, so that an attacker can use a reverse search to find the password. Rainbow tables are easily accessible for all hash algorithms for passwords under 16 characters.

There are several common solutions to this problem. One of them is to execute the hash many (about 1000) times. The exact number of times must be known and predetermined by both the client and server so that they can do the same. This has the advantage and the disadvantage that creating hash generation is expensive. It becomes harder for an attacker to work with 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 (usually called a salt) to the password to make it long (maybe 64 characters). This salt should be known to both the client and the server in advance. This solution is cheap and easy, and it doesn't even matter if the salt has leaked.

There is another common problem with password hashing. If a malicious user knows the hash of the user's password, this is as good as knowing the password itself for a poorly designed system. Suppose we have an RPC function that requires a username and password hash. An attacker who knows the password hash can send it without even knowing the password and gain access to the system. This well-known password hash will continue to work until the user changes his password, which can be months or years. A way is needed to limit the duration of using a password hash. This is achieved through the use of dynamic salt.

Authentication then becomes a multi-step process.

  • The client connects to the server and represents some kind of client (or device) identifier, such as a UUID.
  • The server then generates a dynamic salt for this client identifier. Dynamic salt is only good for a short period of time (usually from a few minutes to several hours).
  • The server stores the dynamic salt, its expiration, and the associated client identifier in the database table for future use.
  • The server returns the dynamic salt back to the client along with its expiration.
  • The client hashes the password using one of the above two mechanisms, again combines the dynamic salt, hashes, and then tries to authenticate using the username, client ID and dynamically salted hash.
  • The server validates the credentials provided by checking the hash of the user’s password, known for the passed value, trying to concatenate and hash every known dynamic salt for this client identifier. If a match is found, authentication is accepted.

This is (approximately) the mechanism used by MySQL. It's secure enough that you can use it safely without SSL, but I always recommend using SSL so that the rest of the payload is protected.

If you use secure mechanisms like this, it doesn't really matter if you use the MD5 or SHA variant. However, for any new development, it would not make sense to use SHA256 if there weren’t a very good reason why MD5 was needed.

+17
source

md5 is not a good idea - there are currently many really fast rainbow tables to decrypt.

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

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] } 
+1
source

Source: https://habr.com/ru/post/956199/


All Articles