Cryptographic Hashing - Protecting Stored Passwords
About 2 min read
A hash is a one-way function that transforms data of arbitrary length into a fixed-length value. It plays a vital role in storing passwords, used to keep them securely in a form from which the original password cannot be recovered. The same input always produces the same hash value, but computing the original data back from a hash value is computationally infeasible.
The Difference Between Hashing and Encryption
Hashing and encryption are concepts that are easily confused, but there is a decisive difference between them. Encryption is a two-way transformation: with the correct key, the original data can be decrypted. Hashing, in contrast, is a one-way transformation that cannot be reverted to the original data, and the concept of decryption does not exist. Hashing is well suited for storing passwords, because the service does not need to retain the plaintext of the password, and even if the database is breached, the original passwords are not directly exposed. Conversely, encryption is well suited for protecting data in transit, since it would be meaningless if the recipient could not read the data.
Use in Password Storage
In secure systems, passwords are not stored in plaintext but as hashed values. At login, the entered password is hashed and compared with the stored hash value. Representative hash algorithms include SHA-256, bcrypt, and Argon2. SHA-256 is fast, but too fast for password use, so bcrypt and Argon2, which deliberately raise the computational cost, are recommended. As of 2025, OWASP positions Argon2id as the most recommended password hashing algorithm. The higher the computational cost, the greater the resistance to brute-force attacks.
Why Migrating Off an Old Hash Cannot Be Done in One Pass
When a system that uses an old algorithm for password storage is migrated to a new scheme, the one-way nature of hashing itself becomes the constraint. Since only hash values are stored and they cannot be turned back into the original passwords, the values in the database cannot be converted to the new algorithm's hashes in one batch. The only moment the service can touch the plaintext password is when a user logs in and enters it. Migration in practice therefore proceeds gradually: when a login is verified with the old scheme, the plaintext is re-hashed on the spot with the new algorithm and the stored value is replaced. Hashes for users who do not log in remain in the old format, so during the migration period the system needs a way to tell which format each stored value uses and verify accordingly. It is a good example of how the design advantage of never holding plaintext passwords comes back as extra work at migration time.
The Hashing Process
Practical Pitfalls and Countermeasures
Simple hashing alone is vulnerable to rainbow table attacks. As a countermeasure, the standard approach is to add a salt (random data) before hashing. A common mistake in practice is using old algorithms such as MD5 or SHA-1 for password hashing. These are so fast that a GPU-powered attack can compute a massive number of hashes in a short time. A long, random password retains strong resistance to brute-force attacks even in its hashed state.
Was this article helpful?