If your mobile app has user accounts with passwords, your backend stores those passwords, and how it stores them is one of the highest-stakes decisions in the whole system. Get it wrong, store them in plaintext, encrypt them reversibly, or hash them with a fast general-purpose hash, and a single database breach hands attackers your users' passwords, which they will reuse against your users everywhere. Get it right, with a slow, salted password hashing function, and even a full database leak leaves the passwords expensive to crack. This is server-side work, but it is core to your app's security. Here is how password hashing should work for a mobile app's backend.
Short answer
A mobile app's backend should store passwords using a dedicated, slow, salted password hashing function, never plaintext, reversible encryption, or a fast general-purpose hash. Per OWASP's Password Storage guidance, the recommended algorithm is Argon2id, with bcrypt, scrypt, or PBKDF2 as alternatives, each used with a per-user random salt and tuned cost parameters so hashing is deliberately expensive. Fast hashes like MD5 or SHA-256 are unsuitable for passwords because they can be brute-forced at enormous speed. The point is that even if your database is breached, properly hashed passwords are costly to crack. Hash on the server over TLS, do not treat a client-side hash as the password, and keep the algorithm and parameters current.
What you should know
- Never store plaintext or reversible passwords: a breach exposes them all.
- Use a slow, salted password hash: deliberately expensive to compute.
- Argon2id is recommended: with bcrypt, scrypt, or PBKDF2 as alternatives.
- Fast hashes are unsuitable: MD5 or SHA-256 are brute-forced quickly.
- Hash on the server: a client-side hash just becomes the password.
Why does password hashing matter, and why not fast hashes?
Because breaches happen, and the storage method decides what an attacker gets. If a database holding passwords is breached, and databases are breached, the question is what the attacker walks away with. Plaintext passwords are immediately usable, and reversibly encrypted passwords are nearly as bad, since the key is often nearby. Hashing is the right idea, storing a one-way transformation instead of the password, but the choice of hash is critical. General-purpose hash functions like MD5 or SHA-256 are designed to be fast, and that speed is exactly what makes them wrong for passwords: an attacker with a leaked database can compute billions of candidate hashes per second, cracking weak and common passwords almost instantly, especially without salting. Password hashing functions are instead deliberately slow and resource-intensive, so that each guess costs meaningful time and memory, which makes large-scale cracking expensive. Salting, a unique random value per password, prevents precomputed lookup tables and ensures identical passwords do not produce identical hashes. So the method matters because it determines whether a breach is a catastrophe or a contained, manageable event.
How do you choose an algorithm?
Use a current password hashing function with tuned parameters. The table summarizes the options.
| Algorithm | Notes |
|---|---|
| Argon2id | Recommended; memory-hard, tunable cost |
| bcrypt | Well-established and widely supported |
| scrypt | Memory-hard alternative |
| PBKDF2 | Acceptable where a standards requirement applies |
| Fast hashes (MD5, SHA-256) | Unsuitable for passwords |
Argon2id is the generally recommended choice, a modern, memory-hard function whose cost in time, memory, and parallelism you tune so that hashing is expensive for an attacker but acceptable for a single legitimate login. bcrypt is a well-established and widely supported option that remains a sound choice. scrypt is another memory-hard alternative. PBKDF2 is acceptable, particularly where a standards or compliance requirement points to it, used with a high iteration count. What unites the appropriate choices is that they are purpose-built password hashing functions with a configurable work factor, used with a per-user random salt. Fast general-purpose hashes do not belong here at all, regardless of how they are combined, because their speed defeats the goal. Whichever you choose, set the cost parameters to current guidance and revisit them over time as hardware improves.
How do you store passwords correctly?
Hash on the server with a tuned, salted password function, and keep it current. When a user sets or changes a password, generate a unique random salt and hash the password with your chosen function, Argon2id or a sound alternative, using cost parameters tuned so a single hash takes a deliberate but tolerable amount of work, and store the hash and salt, not the password. On login, hash the submitted password the same way and compare. Always do this on the server, receiving the password over TLS, rather than hashing on the client and sending the hash, since a client-side hash simply becomes the de facto password an attacker could replay. Consider adding a pepper, a secret kept separate from the database, as defense-in-depth, so a database-only breach lacks part of what is needed. Plan to upgrade: as hardware gets faster, increase the cost parameters, and be ready to rehash to a stronger algorithm, for example on the user's next login. And combine strong hashing with the rest of your authentication posture, rate limiting, breach-password checks, and offering multi-factor or passkeys. The principle is that passwords are stored as the output of a slow, salted, current password hashing function computed on the server, so a breach does not hand over usable credentials.
What to watch out for
The first trap is using a fast general-purpose hash like MD5 or SHA-256 for passwords, or storing them in plaintext or reversibly, all of which make a breach catastrophic; use a slow salted password hash. The second is hashing on the client and treating that hash as the password, which just relocates the secret; hash on the server. The third is setting a password hash once and never revisiting the cost parameters as hardware improves. Password storage is server-side, so a pre-submission scan such as PTKD.com (https://ptkd.com), which reads the binary against OWASP MASVS, assesses the app's authentication handling and cryptographic usage, while the password hashing itself is implemented and enforced on your backend.
What to take away
- A mobile backend should store passwords with a slow, salted, dedicated password hashing function, never plaintext, reversible encryption, or a fast general-purpose hash.
- Argon2id is recommended, with bcrypt, scrypt, or PBKDF2 as alternatives, each with a per-user random salt and tuned cost parameters, so a breach leaves passwords expensive to crack.
- Hash on the server over TLS, do not treat a client-side hash as the password, consider a pepper, and raise cost parameters and rehash over time as hardware improves.
- Password storage is server-side; use a pre-submission scan such as PTKD.com to assess your app's authentication and cryptographic handling, and implement hashing rigorously on the backend.

