Los detalles actuales sobre el sistema de almacenamiento de contraseñas de Discourse se encuentran en discourse/docs/SECURITY.md at main · discourse/discourse · GitHub. Al momento de escribir esto, utilizamos PBKDF2-SHA256 con 600.000 iteraciones.
En algunas situaciones, es posible que desees exportar todas las contraseñas hash de Discourse e importarlas en otro sistema. Por ejemplo, podrías estar migrando desde la autenticación integrada de Discourse hacia un sistema SSO personalizado. Recuerda que es imposible extraer las contraseñas originales de la base de datos, por lo que tu sistema de destino debe ser capaz de ejecutar el mismo algoritmo de hash con los mismos parámetros.
Los datos de las contraseñas se almacenan en la tabla user_passwords, que contiene las columnas password_hash, password_salt y password_algorithm. La columna password_algorithm almacena el prefijo completo del algoritmo PHC (por ejemplo, $pbkdf2-sha256$i=600000,l=32$), el cual puede variar por usuario si el número de iteraciones ha aumentado con el tiempo.
Puedes usar el Explorador de Datos para exportar la información en un formato legible por computadora:
SELECT users.id, users.username, up.password_salt, up.password_hash, up.password_algorithm
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
WHERE users.id > 0
Esto exportará los datos en el formato nativo de Discourse. La sal está codificada en hexadecimal y el hash de la contraseña también está codificado en hexadecimal.
Algunos sistemas externos admiten el formato de cadena PHC, que busca ser una forma de representar la salida de una función de hash de contraseñas independiente del algoritmo. Para pbkdf2-sha256, esta cadena contiene el tipo de algoritmo, el número de iteraciones, la sal codificada en base64 y el hash codificado en base64. Afortunadamente, Postgres puede manejar todo esto por nosotros en una sola consulta.
Para generar cadenas PHC para cada usuario de Discourse, puedes usar una consulta del Explorador de Datos como esta:
SELECT users.id, users.username,
concat(
up.password_algorithm,
replace(encode(up.password_salt::bytea, 'base64'), '=', ''),
'$',
replace(encode(decode(up.password_hash, 'hex'), 'base64'), '=', '')
) as phc
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
WHERE users.id > 0
Si utilizas Auth0, entonces necesitas esta consulta en su lugar:
SELECT
user_emails.email,
users.active as email_verified,
concat(
up.password_algorithm,
replace(encode(up.password_salt::bytea, 'base64'), '=', ''),
'$',
replace(encode(decode(up.password_hash, 'hex'), 'base64'), '=', '')
) as password_hash
FROM users
INNER JOIN user_passwords up ON users.id = up.user_id
INNER JOIN user_emails
ON users.id = user_emails.user_id
AND user_emails.primary IS TRUE
AND users.id > 0
