Password Hashing & Salting (2025): Argon2id vs bcrypt, PBKDF2 Explained

Learn hashing vs salting, why Argon2id leads in 2025, and see safe settings with code samples. Plus bcrypt/PBKDF2 guidance and common pitfalls.

 min. read
September 11, 2025
TL;DR:
Password hashing stores passwords by running them through a one-way, intentionally slow function so the original can’t be recovered. Salting adds a unique random value before hashing so identical passwords produce different hashes and rainbow tables fail. Prefer Argon2id in 2025; use PBKDF2 where FIPS is required; bcrypt is acceptable for legacy.

In the 21st century, there have been quite a few data breach incidents, such as Yahoo in 2013, Adobe in 2013, Facebook in 2019, LinkedIn in 2021, etc. Businesses can no longer consider data security an afterthought as a single data breach incident can have dire consequences. 

Even though there have been some new and more secure authentication mechanisms, such as biometric authentication and OTP through WhatsApp or Telegram, for users to log into their apps or software, usernames and passwords are still the primary method of authentication. It is therefore important for businesses to securely store users’ passwords with different techniques, such as hashing and salting, to protect their personal information.

In this blog post, we will be introducing password hashing and salting, two fundamental yet essential techniques in the field of cryptography, and what kinds of attacks hashing and salting can mitigate. 

What Is Password Hashing?

An infographic showing the flow of password hashing, which is a process turning password into a scrambled representation of itself through an algorithm.

Whenever a user creates a new account on a website or app, the username and password are not stored in plain text format. For example, if you create an account on Netflix with the username netflix_user1 and iLoveWatch1ngCom3dy as your password, the password is actually not stored as it is in the database. Developers usually run a function to convert this password into something that looks completely different from its original form through a mathematical algorithm. This process is called hashing and the mathematical algorithm is called hashing algorithm. At first glance, hashing might look similar to encryption but hashing is a one-way function while encryption is a two-way function. In other words, you cannot revert a hashed password, also known as a hash, back to its original plain-text value while it is possible to do that with encrypted values.

Let’s use a hash generator to demonstrate.

When we use the bcrypt algorithm to hash iLoveWatch1ngCom3dy, we will generate a string of characters that looks nothing like iLoveWatch1ngCom3dy as shown below.

  • Password: iLoveWatch1ngCom3dy
  • Hashed password / Hash: $2a$12$CpzXhh5bswd2gNd1eFTNnugGTE8CWUIgpzPivCejVk7JN284V0g96

A little change in the password can make a huge difference. Let’s replace the first “i” with an “u” and see how the hash will look like.

  • Password: uLoveWatch1ngCom3dy
  • Hashed password / Hash: $2a$12$E0V50LSt1hUErz3d05f.ruME6K/.y3YIjRLJOKZyCGmuO7feO.xC.

You can see that the resulting hash is quite different from the previous one.

The value that is stored in the database then is the hash not the actual password. Whenever a user logs into the software or app, the provided value will first be hashed and then checked with the hash stored in the database to verify the user’s identity. In this way, even if hackers manage to obtain the hash, they cannot use it to log in.

Common Hash Algorithms

As mentioned above, hash algorithms are one-way functions that convert a new string of characters with a fixed length. In the early days, Message Digest (MDx) algorithms, such as MD5, and Secure Hash Algorithms (SHA), such as SHA-1 and SHA-2, were used quite often to hash passwords. However, these were designed to be quick. You might wonder why that is an issue. Having a fast hash algorithm means that it takes less computational efforts for attackers to “decrypt” the hash. Furthermore, major players in the field have also identified some vulnerabilities in these algorithms and therefore advise against the adoption of MD5, SHA-1 and SHA-2 for password hashing. Although MD5 is no longer used for password hashing, it can still be used to verify data integrity. 

The Open Web Application Security Project (OWASP) has listed some hash algorithms designed for storing passwords such as Argon2id, bcrypt, and PBKDF2t. 

Argon2id

Argon2 is the hashing algorithm that won the 2015 Password Hashing Competition (PHC). It has three variations, namely Argon2d, Argon2i, and Argon2id.  Argon2id is a hybrid of Argon2i and Argon2id, allowing it to provide a more balanced approach to resisting both side-channel and GPU-based attacks.

The Argon2 algorithm can take a number of configurable parameters, such as memory, iterations, parallelism, salt length, and key length. 

bcrypt

Based on the Blowfish cipher, bcrypt was designed by Niels Provos and David Mazières in 1999. To better protect passwords from different attacks, bcrypt incorporates salting, which will be discussed later, into the process and allows the interaction count to be increased, making it slower and requiring more computational power from the attackers. 

PBKDF2

Password-Based Key Derivation Function 2 (PBKDF2) is recommended by National Institute of Standards and Technology (NIST) and also has higher computational cost compared to the other algorithms. It also has FIPS-140 validated implementation, making it the preferred algorithm when these are mandated. 

You can check the Password Storage Cheat Sheet to check some best practices of hash algorithms.

Which algorithm should I use in 2025?

Short answer

  • Argon2id — default choice for most apps.
  • scrypt — if Argon2id isn’t available.
  • bcrypt — legacy only; beware 72-byte input limit.
  • PBKDF2-HMAC-SHA-256 — when FIPS/NIST compliance is required.

Tuning rule: benchmark on production-like hardware and target <~1s per verify.

Safe starting parameters

  • Argon2id
    • m=46 MiB, t=1, p=1
    • m=19 MiB, t=2, p=1
    • m=12 MiB, t=3, p=1
  • scrypt
    • N=2^17, r=8, p=1
    • N=2^16, r=8, p=2
    • N=2^15, r=8, p=3
    • Each offers similar resistance; they trade memory for CPU.
  • bcrypt
    • cost ≥ 10; enforce ≤72-byte input
  • PBKDF2
    • PBKDF2-HMAC-SHA-256 ≥ 600k iterations
AlgorithmMemory-hard?Starting preset (2025)Best forWatch-outs
Argon2id Yes m=19 MiB, t=2, p=1 Default modern choice Needs RAM; benchmark to <~1s
scrypt Yes N=2^17, r=8, p=1 When Argon2id isn’t available Param names vary by libs; tune memory
bcrypt No cost ≥ 10 Legacy systems 72-byte input limit; not memory-hard
PBKDF2-HMAC-SHA-256 No ≥ 600,000 iterations FIPS/NIST compliance Weaker vs hardware; retune periodically

Limitations of Password Hashing

Even though there is no way for hackers to retrieve passwords from the hashes. There are still a few ways for them to crack the code. 

Hackers can try a brute-force attack by running random passwords through the hash function until they finally find a match. This is rather inefficient since the hash algorithms designed for securely storing passwords are designed to be slow, making the entire process tedious and long. Nonetheless, hackers will eventually manage to crack the code with sufficient time. 

An alternative will be the rainbow table attack. A rainbow table is essentially a huge database with precomputed hash outputs. Once the hackers gain access to the hash database, they can then execute the rainbow table attack by checking if the stolen hashes match any precomputed hash stored in the rainbow table.

In order to increase the complexity of password security and protect users’ passwords from the attacks mentioned above, an additional step called password salting is taken.

Better Password Security with Authgear

No longer have to worry about password salting and hashing

Get Demo

What Is Password Salting or Salting a Hash?

You might wonder if you are reading a hash brown recipe as we are now talking about salting a hash; however, salting a hash, in the field of cryptography, actually means to add an additional string of 32 or more characters to the password before it gets hashed. These strings of data are called salts. Password salting helps developers increase password complexity without affecting user experience. It is important to note that salts should be randomly generated by cryptographically secure functions since adding salts that are quite predictable is actually moot.

A salted hash is the result of adding a unique, random salt to a password before hashing. Salting ensures identical passwords do not create the same hash and defeats rainbow-table attacks. In modern systems, salted and hashed passwords are produced automatically by libraries that store the salt alongside the hash string.

How does that make the hash more unique? Let’s demonstrate it with an example.

Michael and Bob both use the same password s@1t3dH@shBrown by coincidence, they will also have the same hash: $2a$12$xdWgQ5mhv8rSaUK3qdusTO4XdMFbQi6TD/1VvOZjvGm10RXnhZZa2.

However, if Michael’s password is salted with Iwx2ZE and Bob’s password is salted with 0DoVej, they will have completely different salted hashes.

Michael:

  • Password: s@1t3dH@shBrown
  • Salt: Iwx2ZE
  • Salted Input: Iwx2ZEs@1t3dH@shBrown
  • Salted Hash Output: $2a$12$TGRg8FCZvnDm.f4WPNtWQucwRv5zsi4D9Qy/gYgpfFfYx9XpXdE6a

Bob:

  • Password: s@1t3dH@shBrown
  • Salt: 0DoVej
  • Salted Input: 0DoVejs@1t3dH@shBrown
  • Salted Hash Output: $2a$12$VtpXTHf69x1db/71bGHl3eMiEDAkgQe/Gq6UeNOKuHvdg.WnIXEHa

As you can see, their salted hash outputs are quite different even though they share the same password. This makes it very hard for hackers to guess the original password using a rainbow table. It is important to note that each user’s password should have its own unique salt; otherwise, the salting process simply makes the password longer without impeding hackers’ attacks.

With an additional step of salting, the authentication process will be a little bit different. In practice, the salt, the hash, and the username are usually stored together. When someone logs into the software or app, the system will then:

  • Check if the provided username can be found in the database
  • If yes, get the salt that is stored along with that username
  • Add the salt to the provided password by appending or prepending it
  • Hash it and verify if that hash matches the one stored in the database

Note that most modern hash algorithms, such as bcrypt and Argon2id, salt the password before they get hashed to protect passwords from hash table attacks and slow down dictionary and brute-force attacks.

Salting hashes best practices

  • Don’t use the username as the salt.
  • Use a cryptographically-secure pseudorandom number generator to generate salts.
  • Each password should have its own unique salt. Having a systemwide salt for all passwords isn’t very effective. 
  • The length of the salt should at least be as long as the hash output.

How to hash a password (step-by-step)

  1. Generate a unique salt for the user.
  2. Apply a password hashing function (e.g., Argon2id) to hash the password with the salt and chosen parameters.
  3. Store the hashed password output plus the salt and algorithm parameters.
  4. On login, re-compute the hash and compare.
  5. If parameters are outdated, rehash the password and update the record.

Hash vs salt vs pepper

Hash = one-way transformation for verification. Salt = per-user, random value added before hashing. Pepper = application-wide secret stored separately. In short: you hash and salt every password, and optionally add a pepper in the app layer for defense-in-depth.

Frequently asked questions

Is salting the same as hashing?

No. Hashing is a one-way transformation used to verify passwords without storing them in plain text. Salting adds a unique random value to each password before hashing so identical passwords produce different hashes.

Do I still need a salt when using bcrypt?

Modern bcrypt implementations generate and store a unique salt automatically with the hash. You don’t need to manage salts yourself, but you should understand why salting prevents rainbow-table attacks.

What’s a “pepper” and where should I store it?

A pepper is an application-wide secret added in addition to the per-user salt. Store the pepper separately from the database (e.g., in a KMS/HSM or environment secret), never alongside the hash.

Which password hashing algorithm should I use in 2025?

Prefer Argon2id for general use because it’s memory-hard. Use PBKDF2 when you must meet FIPS/NIST requirements. Keep bcrypt only for legacy systems or where Argon2id is unavailable.

What are safe Argon2id parameters?

A good starting point is roughly m ≈ 19–64 MiB, t = 1–3, p = 1. Tune to your hardware so a single verification stays comfortably under ~1 second on your production boxes, then revisit periodically.

Is SHA-256 or SHA-3 alone OK for passwords?

No. General-purpose hashes are too fast for password storage. Use a dedicated password hashing/KDF algorithm such as Argon2id, scrypt, bcrypt, or PBKDF2.

How long should a salt be?

Use a unique, random salt per password, typically 16–32 bytes (≥128 bits) from a CSPRNG.

Where do I store the salt?

Store the salt with the hash (e.g., in the same database row or encoded in the hash string). It is not secret and must be available during verification.

What about the bcrypt 72-byte input limit?

bcrypt only considers the first ~72 bytes of input. Enforce a reasonable maximum length and/or migrate to Argon2id. If you must pre-hash, use an HMAC with a server-side pepper and store the pepper separately.

How do I migrate from bcrypt/PBKDF2 to Argon2id?

Use opportunistic rehashing: verify existing users with the old algorithm, then on successful login, rehash the password with Argon2id and update the stored record. Keep both verifiers during the transition.

When should I rehash existing passwords?

Rehash when your algorithm choice or parameters are no longer considered adequate (e.g., after you raise Argon2id memory/time settings or move from bcrypt to Argon2id). Track a “hash version” with each account.

What’s the difference between hashing and encryption for passwords?

Hashing is one-way and designed for verification. Encryption is reversible and intended for data you must read back. Passwords should be hashed, not encrypted.


Let Authgear Manage Your Users' Passwords

There are many ways one can store passwords incorrectly. For example, do you know that besides picking the right hashing algorithm, a common recommended best practices of prehashing password with SHA256 then bcrypt is actually a security issue?

With Authgear, your users’ passwords will be well secured by industry-standard mechanisms.

Authgear uses Argon2id to salt and hash users' passwords. Moreover, your app will also be equipped with all the security features you need to provide not only better security but also smoother user experience to gain a competitive advantage. 

Contact us now to see how Authgear can help you increase user conversion rate, reduce cost, and provide better user experience. 

Preferences

Privacy is important to us, so you have the option of disabling certain types of storage that may not be necessary for the basic functioning of the website. Blocking categories may impact your experience on the website.

Accept all cookies

These items are required to enable basic website functionality.

Always active

These items are used to deliver advertising that is more relevant to you and your interests.

These items allow the website to remember choices you make (such as your user name, language, or the region you are in) and provide enhanced, more personal features.

These items help the website operator understand how its website performs, how visitors interact with the site, and whether there may be technical issues.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.