Development Security Guide: How to securely store user passwords

Source: Internet
Author: User
Tags hmac scrypt
Development Security Guide: How to securely store user passwords 0 × 00 preface

First, if you are not familiar with the concept and use of cryptography, or you are in need of some cryptographic guidance, I recommend that you read this article.

Previously, we made it clear that even security recommendations should have a shelf life. Therefore, unlike most blog posts we published in the past, the content above is actually in a "update at any time" status: when security requirements change and new forms of attacks are discovered, we will make corresponding changes.

Here we propose a password security point: do not store the plaintext password, but store the hash value of the password.

In fact, it is very simple to generate a secure password hash value.

However, there is a problem here: you may want someone else to set up a password-based account. with this account and password, someone else can log on to your program, how can this function be securely implemented?

It's easy to solve this problem-use libsodium. It provides a secure password hash API for most languages. Earlier than Version 1.0.8, it used the scrypt algorithm, but from version 1.0.9, it also provided Argon2, an algorithm carefully selected from the recent hash password comparison. Libsodium provides binding to most programming languages.

Libsodium file

Libsodium source code

Note: an attack on Argon2i-a variant of Argon2 universal password hash is published here. In fact, the impact is not serious, but it may lead to a new variant (maybe Argon2x, because it may use XOR instead of overwriting the memory to mitigate these attacks ).

If you cannot reconcile libsodium with your requirements for various reasons, you have other options. When preparing this blog, our team has studied several cryptographic hash libraries in multiple programming languages. The following describes how to use the sample code.

Currently, the following cryptographic hashing algorithms are supported:

Champion of Argon2 password hash competition

Bcrypt

Scrypt

Other algorithms used in the password hash competition (Catena, Lyra2, Makwa, and yescrypt)

PBKDF2 is the worst choice

0 × 01 first PHP solution

First, check whether your version supports PHP. If yes, the PHP Password API can be used. If not, try upgrading. if not, check password_compat.

$hash = password_hash($userPassword, PASSWORD_DEFAULT);

Apparently password_hash () uses the hash value calculated by adding salt. Adjust the value based on your actual situation. if the hardware supports the value, it is good to use the minimum absolute value of 10.12. the default value is 10.

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

In fact, it is very easy to verify the hash storage of a password:

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    }}

In PHP7, PASSWORD_DEFAULT still uses bcrypt. In future versions, it may gradually become Argon2.

PHP solution 2

If you cannot use libsodium (we strongly recommend that you use it), you can still use PHP to encrypt the hash by using the Scrypt PHP extension from Dominic Black of PECL.

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

Next, bind a PHP package to your project.

# Hashing$hash = \Password::hash($userProvidedPassword);# Validationif (\Password::check($userProvidedPassword, $hash)) {    // Logged in successfully.}
0 × 02 first JAVA solution

Implements secure password hashing in Java programs. besides libsodium and jBCrypt, it provides the bcrypt hashing algorithm.

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

Verify a bcrypt hash in Java:

if (BCrypt.checkpw(userProvidedPassword, hash)) {    // Login successful.}
JAVA solution 2

There is a scrypt implemented in java, but it requires you to specify the parameter without providing a default value for you.

# Calculating a hashint N = 16384;int r = 8;int p = 1;String hashed = SCryptUtil.scrypt(passwd, N, r, p);# Validating a hashif (SCryptUtil.check(passwd, hashed)) {    // Login successful}
0 × 03 C #. net c # (. NET) solution 1

We recommend Martin Steel's BCrypt. NET fork instead of System. Security. Cryptography. Rfc2898DeriveBytes, which is a PBKDF2-SHA1 (we don't mean that the PBKDF2-SHA1 is not secure, but bcrypt is relatively better.

// Calculating a hashstring hash = BCrypt.HashPassword(usersPassword, BCrypt.GenerateSalt());// Validating a hashif (BCrypt.Verify(usersPassword, hash)) {    // Login successful}
C # (. NET) solution 2

Here there is also a Scrypt package in NuGET.

// This is necessary:ScryptEncoder encoder = new ScryptEncoder();// Calculating a hashSecureString hashedPassword = encoder.Encode(usersPassword);// Validating a hashif (encoder.Compare(usersPassword, hashedPassword)) {    // Login successful}
0 × 04 Ruby first solution

As I have always done, here is a Ruby gem for the hash of bcrypt passwords.

require "bcrypt"# Calculating a hashmy_password = BCrypt::Password.create(usersPassword)# Validating a hashif my_password == usersPassword  # Login successful

It should be noted that, as of the end of this article, the library still does not follow the best practices of encryption. Therefore, they need to take this into account before taking the time to patch.

Ruby solution 2

Scrpyt hash in Ruby

This is also a Ruby gem used to hash bcrypt passwords.

require "scrypt"# Calculating a hashpassword = SCrypt::Password.create(usersPassword)# Validating a hashif password == usersPassword  # Login successful
0 × 05 first Python solution

All right, you guess. use the bcrypt python package (GitHub)

import bcryptimport hmac# Calculating a hashpassword = 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

Python developers usually prefer passlib (Bitbucket), although its API name is incorrect. ("Encryption" instead of "hash "):

from passlib.hash import bcrypt# Calculating a hashhash = bcrypt.encrypt(usersPassword, rounds=12)# Validating a hashif bcrypt.verify(usersPassword, hash):    # Login successful
Python solution 2

Currently, we find that only django-scrypt package is available except libsodium. We are still searching for others.

0 × 06 Node. js Node. js solution 1

On Node. js, bcrypt (https://www.npmjs.com/package/bcrypt) has two secure implementations, Although bcrypt looks preferred.

In the following example, Promises is widely used to simplify error handling:

var Promise = require("bluebird");var bcrypt = Promise.promisifyAll(require("bcrypt"));function addBcryptType(err) {    // Compensate for `bcrypt` not using identifiable error types    err.type = "bcryptError";    throw err;}// Calculating a hash:Promise.try(function() {    return bcrypt.hashAsync(usersPassword, 10).catch(addBcryptType);}).then(function(hash) {    // Store hash in your password DB.});// Validating a hash:// Load hash from your password DB.Promise.try(function() {    return bcrypt.compareAsync(usersPassword, hash).catch(addBcryptType);}).then(function(valid) {    if (valid) {        // Login successful    } else {        // Login wrong    }});// You would handle errors something like this, but only at the top-most point where it makes sense to do so:Promise.try(function() {    // Generate or compare a hash here}).then(function(result) {    // ... some other stuff ...}).catch({type: "bcryptError"}, function(err) {    // Something went wrong with bcrypt});
Node. js solution 2

We recommend scrypt for humans, which is a node-scrypt package friendly to developers and is very easy to use.

var Promise = require("bluebird");var scrypt = require("scrypt-for-humans");// Calculating a hash:Promise.try(function() {  return scrypt.hash(usersPassword);}).then(function(hash) {  // Store hash for long term use});// Validating a hash:Promise.try(function() {  return scrypt.verifyHash(usersPassword, hash);}).then(function() {  // Login successful}).catch(scrypt.PasswordError, function(err) {  // Login failed});

* Original article address: paragonie, Edison Chen of Dong'er men/compile 0xroot for later sorting. for details, refer to FreeBuf hacker and geek (FreeBuf. COM)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.