Talking about hashing and encryption to a friend, he later got knee about hashing and asked me this question that I later discover that it was almost a trending question on the internet. His question was
for extra layer of security to ones password, why not hash an already hashed password?
Like an example:
<?php $password = 'ilovepassword1'; $securepass = sha1(md5(md5(sha1(md5(sha1($password)))))); echo $securepass; ?>
he saw from Why Can’t You Hash a Password Multiple Times.
This seems very brilliant and smart, his argument was “when one tries to combine different hash functions it makes the process of computing the hash slower, so cracking is slower making you more secure”.
Think of this like using a sharp object on your fingers to draw extra marks or lines so that your can alter your finger prints and make your finger prints more secure.
But in practice, though, there is very little benefit to doing it. All it does is create interoperability problems, and can sometimes even make the hashes less secure. As a good golden rule that you might want to adopt, “Never try to invent your own crypto, always use a standard that has been designed by experts”.
Before we go further, lets use the common hash functions for this explanation.
- SHA: The SHA (Secure Hash Algorithm) is one of a number of cryptographic hash functions published by the National Institute of Standards and Technology (NIST) as a U.S. Federal Information Processing Standard (FIPS), including:
- MD5: The MD5 (Message-Digest Algorithm) is crypthographic hash function that generates a 128-bit hash value. MD5 is used in to check data integrity and in security applications. In other words MD5 checksum is like a fingerprint of the file. There is a very small possibility that two identical MD5 hash values are generated of two different files. That is way MD5 hashes have a lot of uses, some of which are: detecting data changes, storing or obscuring the passwords, making unique keys in databases and ensuring message integrity.
The MD5 algorithm is designed to be quite fast on 32-bit machines. In addition, the MD5 algorithm does not require any large substitution tables; the algorithm can be coded quite compactly.
MD5 was designed by Ronald Rivest in 1991 to replace an earlier hash function MD4. The source code in RFC 1321 contains a “by attribution” RSA license.
Instead of all those stress of hashing an already hashed password or file, one of the best thing to do is add a “salt” to it. E.g.
Hashing a word MD5:
|MD5 hash value
with the above example, anyone can easily check for the hashed value and get a match for b068931cc450442b63f5b3d276ea4297, and will easily figure out the actual data or even password.
So instead of going through the stress of hashing an already hashed file or password for extra layer of security, one can add a salt
Salt helps to thwart pre-computed dictionary attacks.
Suppose an attacker has a list of likely passwords. He can hash each and compare it to the hash of his victim’s password, and see if it matches. If the list is large, this could take a long time. He doesn’t want spend that much time on his next target, so he records the result in a “dictionary” where a hash points to its corresponding input. If the list of passwords is very, very long, he can use techniques like a Rainbow Table to save some space. This gives the user the ability to use any password like “iloveyou”, but behind the sence, and extra work is done to the hash value.
However, suppose his next target salted their password. Even if the attacker knows what the salt is, his precomputed table is worthless—the salt changes the hash resulting from each password. He has to re-hash all of the passwords in his list, affixing the target’s salt to the input. Every different salt requires a different dictionary, and if enough salts are used, the attacker won’t have room to store dictionaries for them all. Trading space to save time is no longer an option; the attacker must fall back to hashing each password in his list for each target he wants to attack.
So, it’s not necessary to keep the salt secret. Ensuring that the attacker doesn’t have a pre-computed dictionary corresponding to that particular salt is sufficient.
$hashed_password = hash( $salt . $password )
That is, if a user’s password is “name” and the salt is “P9 vx” then we’ll hash “P9 vxname”.
Another good example gotten from wikipedia
The salt value is generated at random and can be any length, in this case the salt value is 8 bytes (64-bit) long. The hashed value is the hash of the salt value appended to the plaintext password. Both the salt value and hashed value are stored.
|String to be hashed
|Hashed value = SHA256 (Password + Salt value)
As you can see from the hashed value, even though the plaintext passwords are the same, the hashed values are different. Additionally, dictionary attacks are mitigated to a degree as an attacker cannot practically precompute the hashes. However, a salt cannot protect against common or easily-guessed passwords.
Benefits of using salt
- The modern shadow password system, in which password hashes and other security data are stored in a non-public file, somewhat mitigates these concerns. However, they remain relevant in multi-server installations which use centralized password management systems to push passwords or password hashes to multiple systems. In such installations, the root account on each individual system may be treated as less trusted than the administrators of the centralized password system, so it remains worthwhile to ensure that the security of the password hashing algorithm, including the generation of unique salt values, is adequate.
- Salts also make dictionary attacks and brute-force attacks for cracking large numbers of passwords much slower (but not in the case of cracking just one password). Without salts, an attacker who is cracking many passwords at the same time only needs to hash each password guess once, and compare it to all the hashes. However, with salts, each password will likely have a different salt; so each guess would have to be hashed separately and compared for each salt, which is considerably slower than comparing the same single hash to every password.
- Another (lesser) benefit of a salt is as follows: two users might choose the same string as their password, or the same user might choose to use the same password on two machines. Without a salt, this password would be stored as the same hash string in the password file. This would disclose the fact that the two accounts have the same password, allowing anyone who knows one of the account’s passwords to access the other account. By salting the passwords with two random characters, even if two accounts use the same password, no one can discover this just by reading hashes.
$hashed_password = hash( $pepper . $salt . $password )
Another example from wikipedia
The password is not stored, and the 8-byte (64-bit) pepper 44534C70C6883DE2 is stored in a secure location separate to the hashed values.
|String to be Hashed
|Hashed Value = SHA256(Password + Pepper)
In contrast to a salt, a pepper does not on its own protect against identifying users who have the same password, but it does protect against dictionary attacks unless the attacker has the pepper value. As a pepper will not be shared between applications, an attacker will be unable to directly match hashes from one leaked database to another.
NB: Using the
pepper does add to the strength of the password hash if compromise of the database does not imply compromise of the application. Without knowledge of the pepper the passwords remain completely secure. Because without the specific password salt you even can’t find out if two passwords in the database are the same or not.