Hashing un mot de passe en Java

Hachage d'un mot de passe en Java

1. Vue d'ensemble

Dans ce didacticiel, nous discuterons de l'importance du hachage des mots de passe.

Nous allons jeter un rapide coup d'œil à ce que c'est, pourquoi c'est important et quelques moyens sécurisés et non sécurisés de le faire en Java.

2. Qu'est-ce que le hachage?

Le hachage est le processus de génération d'une chaîne, ouhash, à partir d'unmessage donné en utilisant une fonction mathématique connue sous le nom decryptographic hash function.

Bien qu'il existe plusieurs fonctions de hachage, celles qui sont adaptées au hachage de mots de passe doivent posséder quatre propriétés principales pour être sécurisées:

  1. Ce devrait êtredeterministic: le même message traité par la même fonction de hachage devraitalways produire le mêmehash

  2. Ce n’est pasreversible: il n’est pas pratique de générer unmessage à partir de seshash

  3. Il a desentropy élevés: un petit changement demessage devrait produire unhash très différent

  4. Et il résiste àcollisions: deuxmessages différents ne devraient pas produire les mêmeshash

Une fonction de hachage possédant les quatre propriétés est un candidat idéal pour le hachage de mot de passe car, ensemble, elles augmentent considérablement la difficulté de rétro-ingénierie du mot de passe à partir du hachage.

Aussi, cependant,password hashing functions should be slow. Un algorithme rapide faciliterait les attaquesbrute force dans lesquelles un hacker tentera de deviner un mot de passe en hachant et en comparant des milliards (or trillions) de mots de passe potentiels par seconde.

Certaines fonctions de hachage qui répondent à tous ces critères sont PBKDF2, BCrypt, andSCrypt.  Mais tout d'abord, jetons un coup d'œil à certains algorithmes plus anciens et expliquons pourquoi ils ne sont plus recommandés

Notre première fonction de hachage est l’algorithme MD5 Message Digest, développé en 1992.

LesMessageDigest de Java facilitent le calcul et peuvent toujours être utiles dans d'autres circonstances.

Cependant, au cours des dernières années,MD5 was discovered to fail the fourth password hashing property pense qu'il est devenu facile par calcul de générer des collisions. Pour couronner le tout, MD5 est un algorithme rapide et donc inutile contre les attaques par force brute.

Pour cette raison, MD5 n'est pas recommandé.

Ensuite, nous examinerons SHA-512, qui fait partie de la famille Secure Hash Algorithm, une famille qui a commencé avec SHA-0 en 1993.

4.1. Pourquoi SHA-512?

À mesure que les ordinateurs gagnent en puissance et que nous découvrons de nouvelles vulnérabilités, les chercheurs développent de nouvelles versions de SHA. Les nouvelles versions ont une longueur de plus en plus longue, ou parfois les chercheurs publient une nouvelle version de l'algorithme sous-jacent.

SHA-512 représente la clé la plus longue de la troisième génération de l'algorithme.

Alors quethere are now more secure versions of SHA,SHA-512 is the strongest that is implemented in Java.

4.2. Implémentation en Java

Voyons maintenant la mise en œuvre de l'algorithme de hachage SHA-512 en Java.

Tout d'abord, nous devons comprendre le concept desalt. En termes simples,this is a random sequence that is generated for each new hash.

En introduisant ce caractère aléatoire, nous augmentons lesentropy du hachage et nous protégeons notre base de données contre les listes de hachages précompilées appeléesrainbow tables.

Notre nouvelle fonction de hachage devient alors approximativement:

salt <- generate-salt;
hash <- salt + ':' + sha512(salt + password)

4.3. Générer un sel

Pour introduire le sel, nous utiliserons la classeSecureRandom  dejava.security:

SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);

Ensuite, nous utiliserons la classeMessageDigest pour configurer la fonctionSHA-512 hash avec notre salt:

MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(salt);

Et avec cela ajouté, nous pouvons maintenant utiliser la méthodedigest pour générer notre mot de passe haché:

byte[] hashedPassword = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));

Lorsqu'il est utilisé avec du sel,SHA-512 is still a fair option,but there are stronger and slower options out there.

En outre, les autres options que nous allons couvrir ont une caractéristique importante: la force configurable.

5. PBKDF2, BCrypt et SCrypt

PBKDF2, BCrypt et SCrypt sont trois algorithmes recommandés.

Chacun de ceux-ci est lent et chacun a la brillante caractéristique d'avoir une force configurable.

Cela signifie qu'à mesure que la puissance des ordinateurs augmente,we can slow down the algorithm by changing the inputs.

5.2. Implémentation de PBKDF2 en Java

Maintenant,salts are a fundamental principle of password hashing, et nous en avons donc besoin pour PBKDF2 aussi:

SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);

Ensuite, nous allons créer unPBEKeySpec et unSecretKeyFactory que nous allons instancier à l'aide du salgorithmePBKDF2WithHmacSHA1 :

KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

Le troisième paramètre (65536) est en fait le paramètre de force. Il indique le nombre d'itérations pour lesquelles cet algorithme est exécuté, ce qui augmente le temps nécessaire à la production du hachage.

Enfin, nous pouvons utiliser notreSecretKeyFactory pour générer le hachage:

byte[] hash = factory.generateSecret(spec).getEncoded();

5.3. Implémentation de BCrypt et SCrypt en Java

Donc, il s'avère queBCrypt and SCrypt support don’t yet ship with Java, bien que certaines bibliothèques Java les prennent en charge.

Spring Security est l’une de ces bibliothèques.

6. Hachage de mot de passe avec Spring Security

Bien que Java prenne en charge nativement les algorithmes de hachage PBKDF2 et SHA, il ne prend pas en charge les algorithmes BCrypt et SCrypt.

Heureusement pour nous, Spring Security est livré avec la prise en charge de tous ces algorithmes recommandés via l'interfacePasswordEncoder:

  • MessageDigestPasswordEncoder  nous donne MD5 et SHA-512

  • Pbkdf2PasswordEncoder nous donne PBKDF2

  • BCryptPasswordEncoder  nous donne BCrypt, et

  • SCryptPasswordEncoder  nous donne SCrypt

Les encodeurs de mot de passe pour PBKDF2, BCrypt et SCrypt sont tous fournis avec la prise en charge de la configuration de la force souhaitée du hachage de mot de passe.

Nous pouvons utiliser ces encodeurs directement, même sans application basée sur Spring Security. Ou, si nous protégeons notre site avec Spring Security, nous pouvons configurer l'encodeur de mot de passe souhaité via son DSL ou viadependency injection.

Et, contrairement à nos exemples ci-dessus,these encryption algorithms will generate the salt for us internally. L'algorithme stocke le sel dans le hachage de sortie pour une utilisation ultérieure lors de la validation d'un mot de passe.

7. Conclusion

Nous avons donc plongé en profondeur dans le hachage des mots de passe; explorer le concept et ses usages.

Et nous avons examiné certaines fonctions de hachage historiques ainsi que certaines actuellement implémentées avant de les coder en Java.

Enfin, nous avons vu que Spring Security est livré avec ses classes de chiffrement de mots de passe, implémentant un tableau de différentes fonctions de hachage.

Comme toujours, le code estavailable on GitHub.