197 votes

Suggestions de bibliothèque pour hacher les mots de passe en Java

Quelle bibliothèque Java dois-je utiliser pour hacher des mots de passe pour le stockage dans une base de données?

J'espérais simplement prendre le mot de passe en texte brut, ajouter un sel aléatoire, puis stocker le sel et le mot de passe haché dans la base de données.

Ensuite, lorsqu'un utilisateur souhaite se connecter, je peux simplement prendre son mot de passe soumis, ajouter le sel aléatoire de ses informations de compte, le hacher et voir s'il correspond au mot de passe de hachage stocké avec ses informations de compte.

169voto

erickson Points 127945

Pour ce faire, vous pouvez utiliser une fonction intégrée au moteur d’exécution Java. SunJCE sous Java 6 prend en charge PBKDF2, un bon algorithme à utiliser pour le hachage de mot de passe.

 byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 128);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
System.out.println("salt: " + new BigInteger(1, salt).toString(16));
System.out.println("hash: " + new BigInteger(1, hash).toString(16));
 

94voto

Martin Konicek Points 7999

Voici une mise en œuvre complète avec deux méthodes pour faire exactement ce que vous voulez:

String getSaltedHash(String password)
boolean checkPassword(String password, String stored)

Le point est que, même si un attaquant obtient l'accès à votre base de données et le code source, les mots de passe sont toujours en sécurité.

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import org.apache.commons.codec.binary.Base64;

public class Password {
    // The higher the number of iterations the more 
    // expensive computing the hash is for us
    // and also for a brute force attack.
    private static final int iterations = 10*1024;
    private static final int saltLen = 32;
    private static final int desiredKeyLen = 256;

    /** Computes a salted PBKDF2 hash of given plaintext password
        suitable for storing in a database. 
        Empty passwords are not supported. */
    public static String getSaltedHash(String password) throws Exception {
        byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
        // store the salt with the password
        return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
    }

    /** Checks whether given plaintext password corresponds 
        to a stored salted hash of the password. */
    public static boolean check(String password, String stored) throws Exception{
        String[] saltAndPass = stored.split("\\$");
        if (saltAndPass.length != 2)
            return false;
        String hashOfInput = hash(password, Base64.decodeBase64(saltAndPass[0]));
        return hashOfInput.equals(saltAndPass[1]);
    }

    // using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
    // cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
    private static String hash(String password, byte[] salt) throws Exception {
        if (password == null || password.length() == 0)
            throw new IllegalArgumentException("Empty passwords are not supported.");
        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        SecretKey key = f.generateSecret(new PBEKeySpec(
            password.toCharArray(), salt, iterations, desiredKeyLen)
        );
        return Base64.encodeBase64String(key.getEncoded());
    }
}

Nous sommes stocker 'salt$iterated_hash(password, salt)'. Le sel de 32 octets aléatoires, dont le but est que si deux personnes différentes à choisir le même mot de passe, les mots de passe stockés toujours différents. L' iterated_hash, ce qui est fondamentalement hash(hash(hash(... hash(password, salt) ...))) le rend très cher pour un attaquant potentiel qui a accès à votre base de données pour deviner les mots de passe, de hachage, et de rechercher des hachages dans la base de données. Vous avez pour le calcul de ce iterated_hash chaque fois qu'un utilisateur se connecte, mais il ne vous coûtera pas beaucoup par rapport à l'attaquant qui passe près de 100% de leur temps à calculer les hachages.

30voto

Michael Borgwardt Points 181658

BCrypt est une très bonne bibliothèque, et il en existe un port Java .

8voto

Bozho Points 273663

Utilisez MessageDigest pour calculer les hachages (SHA-256 de préférence)

7voto

laz Points 12212

Vous pouvez utiliser le Shiro bibliothèque (anciennement JSecurity) la mise en œuvre de ce qui est décrit par l'OWASP.

Il semblerait également que les JASYPT la bibliothèque dispose d'un utilitaire similaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X