Almacenar y verificar contraseñas en Java (con password4j)

Si quieres almacenar las contraseñas de tus usuarios en Java, debes utilizar una herramienta como Password4J. Hoy explico cómo funciona.

En la última entrada explicaba muy por encima cual es la forma correcta de almacenar y verificar contraseñas de usuarios en una aplicación, pero de forma teórica. Hoy voy a explicar cómo hacer esto en la práctica, con Java y la biblioteca Password4j; para guardar en archivos, bases de datos por JDBC...

Añadiendo la dependencia

Si utilizas maven, basta con añadir la dependencia al pom.xml con las siguientes líneas

<dependencies>
    <!-- Otras dependencias -->
    <dependency>
        <groupId>com.password4j</groupId>
        <artifactId>password4j</artifactId>
        <version>1.6.2</version>
    </dependency>
</dependencies>

Si en cambio utilizas Gradle, basta con declarar el módulo como dependencia en el build.gradle correspondiente:

dependencies {
    // Otras dependencias
    implementation "com.password4j:password4j:1.6.2"
}

Es muy importante verificar que la versión en uso es la más reciente, ya que versiones anteriores podróan tener vulnerabilidades de seguridad. Por tanto, si lees esto en el futuro, vete a mvnrepository y mira la última versión del paquete.

Cifrado de contraseñas

Se puede hacer de varias maneras, pero la más sencilla es instanciando un BcryptFunction y llamando a su método hash con la contraseña en texto plano.

Por ejemplo, este programa lee una línea por consola que es la contraseña que el usuario quiere introducir, para luego generar el "hash" y mostrarla por consola nuevamente:

    public static void main(String[] args) {
        var sc = new Scanner(System.in);
        var bcrypt = BcryptFunction.getInstance(12);

        String enTextoPlano = sc.nextLine();

        var resultado = bcrypt.hash(enTextoPlano).getResult();
        System.out.println(resultado);
    }

En este caso utilizamos 12 rondas para cifrar, pero cuantas más utilicemos mejor (siempre que no tarde más de unos milisegundos en generarla).

Verificando la contraseña

Verificar es el otro método de la clase BcryptFunction de password4j, y se hace de forma muy similar, pasando primero la contraseña en texto plano y posteriormente el hash a utilizar.

    public static void main(String[] args) {
        var sc = new Scanner(System.in);
        var bcrypt = BcryptFunction.getInstance(12);
        var hash = "$2b$12$oG3H0L4Xhg28OHreCFM4zeIQIykLb4y356m6qn9GkbOc9i1.lbUne";

        String enTextoPlano = sc.nextLine();

        var resultado = bcrypt.check(enTextoPlano, hash);
        if (resultado) {
            System.out.println("Contraseña correcta");
        } else {
            System.out.println("Contraseña incorrecta");
        }
    }

Si probamos a ejecutar este código, e introducimos la contraseña 12, nos dirá que es correcta. Si introducimos cualquier otra cosa, fallará.

Conclusión

Generar hash de las contraseñas de tus usuarios es muy sencillo, así como verificarlas. No hay excusa alguna para guardar las contraseñas en texto plano, a pesar de lo que dice alguna gente de que es para poder recordársela al usuario, o cosas del estilo.