Most of today’s applications use login/password in order to authenticate. Users often use the same login/password for different kinds of applications. If the couple is stolen, everybody can access all the applications the user has access to.

+

Most of today’s applications use login/password in order to authenticate. Users often use the same login/password for different kinds of applications. If the pair is stolen, everybody can access all the applications the user has access to.

Too often passwords are stored as clear text. Thus the password can be read directly by the database’s administrator, super users or SQL Injection attack etc. The backup media is also vulnerable.

Too often passwords are stored as clear text. Thus the password can be read directly by the database’s administrator, super users or SQL Injection attack etc. The backup media is also vulnerable.

Line 27:

Line 29:

MessageDigest digest = MessageDigest.getInstance("SHA-1");

MessageDigest digest = MessageDigest.getInstance("SHA-1");

digest.reset();

digest.reset();

−

byte[] input = digest.digest(password.getBytes());

+

byte[] input = digest.digest(password.getBytes("UTF-8"));

}

}

Line 36:

Line 38:

==Why add salt ? ==

==Why add salt ? ==

−

There are two drawbacks to choosing to only store the password’s hash:

+

If each password is simply hashed, identical passwords will have the same hash. There are two drawbacks to choosing to only storing the password’s hash:

−

* It is possible to identify two identical passwords.

+

* Due to the birthday paradox (http://en.wikipedia.org/wiki/Birthday_paradox), the attacker can find a password very quickly especially if the number of passwords the database is large.

−

* Due to the birthday paradox (http://en.wikipedia.org/wiki/Birthday_paradox), the attacker can find a password very quickly especially if the number of password is important in the database.

+

* An attacker can use a list of precomputed hashes (http://en.wikipedia.org/wiki/Rainbow_table) to break passwords in seconds.

In order to solve these problems, a salt can be concatenated to the password before the digest operation.

In order to solve these problems, a salt can be concatenated to the password before the digest operation.

Line 44:

Line 46:

A salt is a random number of a fixed length. This salt must be different for each stored entry. It must be stored as clear text next to the hashed password.

A salt is a random number of a fixed length. This salt must be different for each stored entry. It must be stored as clear text next to the hashed password.

−

In this configuration, an attacker must handle a brute force attack on each individual password. The database is now birthday attack resistant.

+

In this configuration, an attacker must handle a brute force attack on each individual password. The database is now birthday attack/rainbow crack resistant.

A 64 bits salt is recommended in RSA PKCS5 standard.

A 64 bits salt is recommended in RSA PKCS5 standard.

Line 56:

Line 58:

digest.reset();

digest.reset();

digest.update(salt);

digest.update(salt);

−

return digest.digest(password.getBytes());

+

return digest.digest(password.getBytes("UTF-8"));

}

}

Line 79:

Line 81:

digest.reset();

digest.reset();

digest.update(salt);

digest.update(salt);

−

byte[] input = digest.digest(password.getBytes());

+

byte[] input = digest.digest(password.getBytes("UTF-8"));

for (int i = 0; i < iterationNb; i++) {

for (int i = 0; i < iterationNb; i++) {

digest.reset();

digest.reset();

Line 88:

Line 90:

==Complete Java Sample==

==Complete Java Sample==

−

In order to create the table needed by this application, call the method creerTable().

+

In order to create the table needed by this application, call the method createTable().

It creates a TABLE called CREDENTIAL, with these fields :

It creates a TABLE called CREDENTIAL, with these fields :

* LOGIN VARCHAR (100) PRIMARY KEY

* LOGIN VARCHAR (100) PRIMARY KEY

Line 238:

Line 240:

digest.reset();

digest.reset();

digest.update(salt);

digest.update(salt);

−

byte[] input = digest.digest(password.getBytes());

+

byte[] input = digest.digest(password.getBytes("UTF-8"));

for (int i = 0; i < iterationNb; i++) {

for (int i = 0; i < iterationNb; i++) {

digest.reset();

digest.reset();

Line 247:

Line 249:

−

public void creerTable(Connection con) throws SQLException{

+

public void createTable(Connection con) throws SQLException{

Statement st = null;

Statement st = null;

try {

try {

Revision as of 13:46, 9 August 2012

Status

Released 14/1/2008

Introduction

Most of today’s applications use login/password in order to authenticate. Users often use the same login/password for different kinds of applications. If the pair is stolen, everybody can access all the applications the user has access to.

Too often passwords are stored as clear text. Thus the password can be read directly by the database’s administrator, super users or SQL Injection attack etc. The backup media is also vulnerable.
In order to solve this problem, passwords must be stored encrypted. Two kinds of encryption are available:

One way functions (SHA-256 SHA-1 MD5, ..;) also known as Hashing functions

Passwords are secrets. There is no reason to decrypt them under any circumstances. Helpdesk staff should be able to set new passwords (with an audit trail, obviously), not read back old passwords. Therefore, there is no reason to store passwords in a reversible form.

Credential storage.

If the password’s digest is stored in a database, an attacker should be unable to recover the password thanks to the preimage resistance. The only way to go past this would be a brute force attack, i.e. computing the hash of all possible passwords or a dictionary attack, i.e. computing all the often used password.

Why add salt ?

If each password is simply hashed, identical passwords will have the same hash. There are two drawbacks to choosing to only storing the password’s hash:

Hardening against the attacker's attack

To slow down the computation it is recommended to iterate the hash operation n times. While hashing the password n times does slow down hashing for both attackers and typical users, typical users don't really notice it being that hashing is such a small percentage of their total time interacting with the system. On the other hand, an attacker trying to crack passwords spends nearly 100% of their time hashing so hashing n times gives the appearance of slowing the attacker down by a factor of n while not noticeably affecting the typical user.
A minimum of 1000 operations is recommended in RSA PKCS5 standard.

The stored password looks like this :
Hash(hash(hash(hash(……….hash(password||salt)))))))))))))))

To authenticate a user, the operation same as above must be performed, followed by a comparison of the two hashes.

The hash function you need to use depends of your security policy. SHA-256 or SHA-512 is recommended for long term storage.