Bonjour, bonjour, 👋 Faisons ensemble un petit tour d’horizon des bonnes pratiques lorsque l’on s’attaque à la gestion d’un mot de passe dans son application Android.

Tout d’abord, la règle de base, ne jamais stocker un mot de passe en clair. Je pense qu’on est tous d’accord sur ce point. En lisant un peu sur le sujet, je me rends compte que l’objet String n’est pas vraiment notre ami : https://stackoverflow.com/a/53015144 car il y a un risque de le récupérer en dumpant la heap.

Stocker un hash Link to heading

Le mieux, c’est de ne pas stocker le mot de passe en local sur le device et d’utiliser les passkeys mais si le besoin apparaît, nous pouvons tout d’abord stocker le hash SHA-256 du mot de passe. C’est très simple :

val message: ByteArray = ...
val md = MessageDigest.getInstance("SHA-256")
val digest: ByteArray = md.digest(message)
comme indiqué sur Cryptography | Android Developers puis stocker le hash ainsi généré.

Ainsi, pour vérifier que le mot de passe est correct, il nous suffit de faire la même opération avec le mot de passe proposé et si celui-ci correspond exactement au hash stocké alors le mot de passe est correct.

Saler son hash Link to heading

Certains mettent en avant que le hash SHA-256 seul risque d’exister au sein d’une liste de hash pré-compilée alias rainbow table : https://www.baeldung.com/java-password-hashing#2-implementing-in-java.

La contre-mesure est simple, il suffit de rajouter un salt qui n’a pas besoin d’être caché du reste du monde ce qui va nous permettre de le stocker avec notre hash.

import java.security.MessageDigest
import java.security.SecureRandom
...
val message: ByteArray = ...
val md = MessageDigest.getInstance("SHA-256")
val salt = ByteArray(16)
SecureRandom().nextBytes(salt)
val digest: ByteArray = md.digest(message + salt)
Il nous faut alors stocker le hash généré et le salt que l’on utilisera pour générer le hash du mot de passe à vérifier.

Vérification

val message: ByteArray = ...
val salt: ByteArray = ... // Le salt précédemment stocké
val hash: ByteArray = ... // Le hash précédemment stocké
val md = MessageDigest.getInstance("SHA-256")
val digest: ByteArray = md.digest(message + salt)
if (String(hash) == String(digest)) println("OK") else println("NOT OK")

Conclusion Link to heading

J’espère que cette introduction aux bonnes pratiques actuelles pour vérifier le mot de passe sur le device vous sera utile dans vos futurs développements. Tous les retours sont les bienvenus 😉 Une deuxième partie nous attend afin de stocker le mot de passe de manière à pouvoir le retrouver en clair plus tard. Et si l’utilisation des passkeys avec Flutter vous intéresse, c’est le sujet de mon prochain article technique.

Post LinkedIn 1 Publication originale 2