Leave us your email and be up to date!
Subscribe now

The Problem: You want people to be able to create a unique user account, with a password, which they will use to access your application. How can you safely implement this feature?

Easiest SolutionUse libsodium, which provides a secure password hashing API in most languages. As of version 1.0.8 it uses the scrypt algorithm, but in the next release (1.0.9) it will also offer Argon2, the most recent, carefully-selected algorithm from the Password Hashing Competition. Libsodium offers bindings for most programming languages.

Note: There is a published attack on Argon2i, the recommended variant of Argon2 for general purpose password hashing. The practical implications aren't severe, but it may lead to a new variant ("Argon2x" perhaps, since it would presumably use XOR instead of overwriting memory to mitigate these attacks) being christened and recommended.

If you, for whatever reason, cannot reconcile your requirements with installing libsodium, you have other options. In preparing this blog post, our security team has investigated several password hashing libraries in multiple programming languages. What follows is our current recommendations for secure password storage with example code.

Acceptable Password Hashing Algorithms

Although there is disagreement about how to rank them, cryptography experts agree that these algorithms are the only ones you should be using to store passwords in 2016:

  • Argon2, the Password Hashing Competition winner.

  • bcrypt

  • scrypt

  • The other Password Hashing Competition finalists (CatenaLyra2Makwa, and yescrypt)

  • PBKDF2 (nearly everyone except FIPS agrees this is the worst of the acceptable options)

Secure Password Storage in PHP

First, make sure you're using a supported version of PHP. If you are, then the PHP password API will be available for use. If you aren't, consider upgrading. If you can't, check out password_compat.

$hash = password_hash($userPassword, PASSWORD_DEFAULT);

password_hash() takes care of salting the hash, transparently. You can, however, specify your owncost. The absolute minimum value you should consider using is 1012 is good, provided your hardware supports it. The default cost parameter is 10.

$hash = password_hash($userPassword, PASSWORD_DEFAULT, ['cost' => 12]);

Verifying a password against a stored hash is incredibly simple:

if (password_verify($userPassword, $hash)) {
    // Login successful.
    if (password_needs_rehash($userPassword, PASSWORD_DEFAULT, ['cost' => 12])) {
        // Recalculate a new password_hash() and overwrite the one we stored previously

As of PHP 7, PASSWORD_DEFAULT still uses bcrypt. In a future version, it may migrate to Argon2.

Alternative: Scrypt Password Hashing in PHP

If you aren't using libsodium (which we strongly recommend that you do use!), you can still get scrypt hashes in PHP through Dominic Black's Scrypt PHP Extension from PECL.

# If you don't have PECL installed, get that first.
pecl install scrypt
echo "extension=scrypt.so" > /etc/php5/mods-available/scrypt.ini
php5enmod scrypt

Next, grab a copy of the bundled PHP wrapper and include it in your project.

# Hashing
$hash = Password::hash($userProvidedPassword);
# Validation
if (Password::check($userProvidedPassword, $hash)) {
    // Logged in successfully.

Secure Password Storage in Java

Your best bet for secure password hashing in a Java application, outside libsodium, is jBCrypt, which provides the bcrypt password hashing algorithm.

String hash = BCrypt.hashpw(userProvidedPassword, BCrypt.gensalt());

Verifying a bcrypt hash in Java:

if (BCrypt.checkpw(userProvidedPassword, hash)) {
    // Login successful.

Alternative: Scrypt Password Hashing in Java

There is a Java implementation of scrypt, but it requires you to specify the parameters rather than providing sane defaults.

# Calculating a hash
int N = 16384;
int r = 8;
int p = 1;
String hashed = SCryptUtil.scrypt(passwd, N, r, p);

# Validating a hash
if (SCryptUtil.check(passwd, hashed)) {
    // Login successful

Secure Password Storage in C# (.NET)

We recommend Martin Steel's BCrypt.NET fork overSystem.Security.Cryptography.Rfc2898DeriveBytes, which is PBKDF2-SHA1.

// Calculating a hash
string hash = BCrypt.HashPassword(usersPassword, BCrypt.GenerateSalt());

// Validating a hash
if (BCrypt.Verify(usersPassword, hash)) {
    // Login successful

We will update this section when we can recommend a safe and reliable library to use.

Alternative: Scrypt Password Hashing in C# (.NET)

There is an Scrypt package in NuGET as well.

// This is necessary:
ScryptEncoder encoder = new ScryptEncoder();
// Calculating a hash
SecureString hashedPassword = encoder.Encode(usersPassword);
// Validating a hash
if (encoder.Compare(usersPassword, hashedPassword)) {
    // Login successful

Secure Password Storage in Ruby

From the author of "Use bcrypt. Use bcrypt. Use bcrypt..." comes a Ruby gem for bcrypt password hashing.

require "bcrypt"

# Calculating a hash
my_password = BCrypt::Password.create(usersPassword)
# Validating a hash
if my_password == usersPassword
  # Login successful

Alternative: Scrypt Hashing in Ruby

There is also a Ruby gem for scrypt password hashing.

require "scrypt"

# Calculating a hash
password = SCrypt::Password.create(usersPassword)
# Validating a hash
if password == usersPassword
  # Login successful

Secure Password Storage in Python

You can't go wrong with the bcrypt Python package (also on github):

import bcrypt
import hmac

# Calculating a hash
password = b"correct horse battery staple"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
# Validating a hash (don't use ==)
if (hmac.compare_digest(bcrypt.hashpw(password, hashed), hashed)):
    # Login successful

Alternative: Scrypt Hashing in Python

Currently the only sane scrypt implementation in Python is the django-scrypt package.

Secure Password Storage in Node.js

There are two secure implementations of bcrypt in Node.js, although bcrypt (Github) seems to be the preferred one.

var hash = bcrypt.hashSync(usersPassword);
if (bcrypt.compareSync(usersPassword, hash)) {
  // Login successful
Hack Insight @Hackinsight
Reklama Box3