Dec 282011
 

Storing plain passwords in a database can be very dangerous, any person that can access the database can have all the passwords of the system users, to prevent this; a password must be hashed and the hash should be stored instead of the plain password, when a user logs in, the system hashes the entered password using the same algorithm that was used when storing the password, then it compares the tow hashes if they match; then the user is authenticated.

Using this technique; no one can know the password of the user event the system itself, this way should be used whenever we need to persist passwords such as in databases or configuration files.

I have developed a class called PasswordHasher that does the job, it can use any hashing algorithm that is supported by the language such as SHA-1 and MD5, it also adds a salt to the hashed password for more security, the salt itself is generated using secure RNG (Random Number Generation).

I have implemented PasswordHasher using C# and Java.

Here’s the C# implementation.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace PasswordHashing
{
public class PasswordHasher
{
private const int SALT_SIZE = 8;
private const int B64_SIZE = 12;
private readonly string HASH_ALGORITHM;

public PasswordHasher(string hashAlgorithm)
{
if (hashAlgorithm == null)
throw new ArgumentNullException("hashAlgorithm");
this.HASH_ALGORITHM = hashAlgorithm;
}

private string getNewSalt()
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buffer = new byte[SALT_SIZE];
rng.GetBytes(buffer);
string salt = Convert.ToBase64String(buffer);
return salt;
}

public string HashPassword(string password)
{
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password");

return hashPassword(password, getNewSalt());
}

private string hashPassword(string password, string salt)
{
string saltedPassword = password + salt;
byte[] plainBytes = Encoding.UTF8.GetBytes(saltedPassword);
HashAlgorithm hasher = HashAlgorithm.Create(HASH_ALGORITHM);
if (hasher == null)
throw new Exception("The provided hash algorithm is invalid");
byte[] hashedBytes = hasher.ComputeHash(plainBytes);
string hash = Convert.ToBase64String(hashedBytes);
string saltedHash = hash + salt;
return saltedHash;
}

public bool ValidatePassword(string password, string hashedPassword)
{
string salt = hashedPassword.Substring(hashedPassword.Length - B64_SIZE);
string saltedHash = hashPassword(password, salt);
bool v = saltedHash == hashedPassword;
return v;
}
}
}

And here’s the Java implemetation:

package hashing;

import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.misc.BASE64Encoder;

public class PasswordHasher {

private final int SALT_SIZE = 8;
private final int B64_SIZE = 12;
private String hashAlgorithm;

public PasswordHasher(String hashAlgorithm) {
if (hashAlgorithm == null || "".equals(hashAlgorithm)) {
throw new IllegalArgumentException();
}
this.hashAlgorithm = hashAlgorithm;
}

private String getNewSalt() throws NoSuchAlgorithmException {
SecureRandom sr = new SecureRandom();
byte[] buffer = sr.generateSeed(SALT_SIZE);
sr.nextBytes(buffer);
String a = sr.getAlgorithm();

BASE64Encoder enc = new BASE64Encoder();
String salt = enc.encode(buffer);
return salt;
}

public String hashPassword(String password) throws NoSuchAlgorithmException {
if (password == null || "".equals(password)) {
throw new IllegalArgumentException();
}
return hashPassword(password, getNewSalt());
}

private String hashPassword(String password, String salt) throws NoSuchAlgorithmException {
String saltedPassword = password + salt;
byte[] plainBytes = null;
try {
plainBytes = saltedPassword.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(PasswordHasher.class.getName()).log(Level.SEVERE, null, ex);
}
MessageDigest md = MessageDigest.getInstance(hashAlgorithm);
byte[] hashedBytes = md.digest(plainBytes);
String hash = new BASE64Encoder().encode(hashedBytes);
String saltedHash = hash + salt;
return saltedHash;
}

public boolean validatePassword(String password, String hashedPassword) throws NoSuchAlgorithmException {
String salt = hashedPassword.substring(hashedPassword.length() - B64_SIZE);
String saltedHash = hashPassword(password, salt);
boolean v = saltedHash.equals(password);
return v;
}

public static void main(String[] args) {
try {
PasswordHasher sha1 = new PasswordHasher("SHA-1");
PasswordHasher md5 = new PasswordHasher("MD5");
String password = "qwerty12345";
String hashedPassword1;
hashedPassword1 = sha1.hashPassword(password);
String hashedPassword2 = md5.hashPassword(password);
System.out.println("SHA-1:" + hashedPassword1);
System.out.println("MD5:" + hashedPassword2);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(PasswordHasher.class.getName()).log(Level.SEVERE, null, ex);
}

}
}

The two images below shows the output of hashing the word “querty” using SHA-1 and MD5 after fixing the salt.

I hope that was useful.

  2 Responses to “Hashing passwords to be stored in a database”

  1. Thanks for your tutorial.

  2. You are welcome

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>