Excerpt: Hashing and encryption are sometimes discussed as interchangeable ways of protecting data. Studying their different purposes has helped me understand why a secure application should normally verify a password without being able to recover it. One Question Separates The Two Controls During my MSc Cyber Security studies at Arden University Berlin, I recently examined the difference between hashing and encryption. The most useful question I took from the lesson is: Does the application need to recover the original value? Encryption is designed to be reversible. An application encrypts plaintext using a key and later uses an appropriate key to decrypt the ciphertext. This is suitable for information that authorised users or systems must retrieve in its original form. Password authentication is different. An application normally needs to determine whether the password entered during login is correct. It does not need to display or recover the original password. This makes one-way password hashing the appropriate approach. An Illustrative PHP/MySQL Example Consider a PHP/MySQL membership system. This is an illustrative scenario rather than a claim about one of my applications. When a user creates an account, the application could make a serious mistake by inserting the submitted password directly into its database. Anyone who later obtains database access may then be able to read every password immediately. Encrypting the passwords would improve protection against someone who obtained only the database. However, the application would also need access to a decryption key. If both the encrypted passwords and that key were compromised, the original passwords could be recovered. A safer authentication design uses PHP’s password-handling functions: $hash = password_hash($password, PASSWORD_ARGON2ID); The resulting hash is stored in the database. During login, PHP can test the submitted password: if (password_verify($submittedPassword, $storedHash)) { // Password matches } password_verify() checks whether the password corresponds to the stored hash. PHP documents that the hash produced by password_hash() contains the algorithm, cost and salt information required for verification. The original password does not need to be recovered. Why an ordinary SHA-256 hash is not enough Learning that passwords should be hashed raises another question: can a developer simply calculate a SHA-256 hash and save the result? That would still be inadequate. General-purpose hash functions are built to process data quickly. If an attacker steals the password hashes, that speed allows large numbers of possible passwords to be tested rapidly. A password-hashing algorithm intentionally makes every guess more computationally expensive. OWASP recommends Argon2id for new applications and provides scrypt, bcrypt and PBKDF2 guidance for situations with different technical or compliance requirements. It also advises using a unique salt for each password. A salt is not a secret key. It is a unique value included in the password-hashing process. It helps ensure that two accounts using the same password do not automatically receive identical stored hashes and reduces the usefulness of precomputed tables. PHP’s password_hash() generates a random salt automatically. Its documentation discourages manually providing one. Defensive Controls Beyond The Hashing Function Secure password storage requires more than selecting an algorithm. First, an application should use its language or framework’s established password API instead of designing a custom hashing method. For PHP, the password_hash(), password_verify() and password_needs_rehash() functions support hashing, verification and later upgrades. Second, the database account used by the application should receive only the permissions it requires. Password hashing reduces the impact of database exposure, but it does not replace access control, secure coding, patching, monitoring or database protection. Third, login attempts should be rate-limited. Hashing slows offline guessing after hashes have been stolen, while rate limiting addresses repeated guesses made through the live application. Finally, multi-factor authentication can reduce reliance on a password as the only barrier to an account. It does not make poor password storage acceptable, but it provides an additional authentication layer. NIST’s current guidance requires passwords to be salted and hashed using a suitable password-hashing scheme. It explains that a cost factor should make offline guesses expensive and should be increased over time where practical. Limitations and Trade-offs Password hashing cannot make a weak password strong. An attacker may still recover common or predictable passwords by guessing them, especially after obtaining the database. Increasing the algorithm’s cost makes attacks more expensive, but it also consumes application resources during legitimate registration and login. The chosen configuration therefore needs performance testing. A cost that is too low offers weaker resistance; one that is too high may cause slow authentication or create denial-of-service concerns. Older systems may also contain hashes produced with outdated algorithms or insufficient costs. Migration does not always require resetting every password immediately. After a successful login, an application can use password_needs_rehash() to identify whether the verified password should be stored again using the newer settings. Key Takeaways Hashing and encryption are not interchangeable. Passwords should normally be processed using a purpose-built password-hashing algorithm because the original values do not need to be recovered. Data that must later be read in its original form may require encryption and careful key management. For me, the deeper development lesson is to begin with the application’s real requirement. Before selecting a protection method, ask whether the system needs to recover the data or merely verify it. That decision determines whether encryption or hashing fits the purpose. Sources Technical guidance checked on 23 October 2026: • OWASP Password Storage Cheat Sheet • PHP Manual: password_hash() • PHP Manual: password_verify() • NIST SP 800-63B: Authentication and Authenticator Management