Fortunately, progress has also been made in hashing technology that hampers high-speed password cracking attempts and makes it uneconomical for attackers to pre-calculate tables – even if the actual password to be cracked is weak. From a certain password length, calculating and storing rainbow tables is no longer viable in a reasonable amount of time. Therefore, an additional, random character string – a "salt" – is added to the password a user has entered. The newly created character string is passed through a hashing algorithm, and the resulting hash is stored in a file such as /etc/shadow. However, the salt must be known if a system is to compare subsequent password entries with the hash. The salt is therefore added to the beginning of the stored hash in plain text. Storing the salt in plain text may sound contradictory at first glance, but the salt doesn't need to be secret, it only needs to be random. Its only purpose is to inflate the potential number of combinations for each individual password in order to exponentially increase the effort required to create rainbow tables.
However, a salt has only little impact when an individual password is attacked with brute force. Conventional hashing algorithms such as those for generating digital signatures or fingerprinting files are optimised for speed. This is counterproductive when checking passwords, as the intended aim is to thwart password crackers. Brute-force attacks can be rendered unattractive by intentionally slowing down the hashing algorithm or by hashing multiple times. For users, the required speed isn't really an issue: They won't notice if checking a password they enter when logging into a system takes a microsecond instead of a millisecond. A password cracker, on the other hand, will become a thousand times slower – instead of 100 million passwords per second, it will only be able to try out 100,000 passwords per second, and a brute-force attack on a password called "P4ssW0r7" would take 48 years instead of 18 days.
The method of artificially slowing things down has its origins in the derivation of crypto keys from passwords. As users' passwords tend to be too short and have too little entropy, keys need to be lengthened securely, for example when encrypting via AES and 256 bits. Cryptographers call this "key stretching", and they achieve it by sending a password through a hashing algorithm multiple times. The method has been standardised as Password-Based Key Derivation Function 2 (PBKDF2) and is, for instance, used in wireless networks with WPA-PSK keys. Smartphones use PBKDF to encrypt backup files with a password before exporting them. The method also successfully thwarts cracking attempts in those situations.
A simple round function for hashing a password multiple times could look like this:
key = hash(password)
for 1 to rounds do
key = hash(key)
Each time, the resulting hash value is simply resubmitted to the hash function as a parameter. More complex round functions may, for instance, add the password to each value before it gets hashed. An operating system or application only needs to perform this exercise once per password and user. A cracking program, on the other hand, must perform it for every possible character combination – and each round adds processing time, so that the overall procedure for each password is slowed down immensely.