I dettagli attuali sul sistema di archiviazione delle password di Discourse sono disponibili all’indirizzo discourse/docs/SECURITY.md at main · discourse/discourse · GitHub. Al momento della stesura, utilizziamo PBKDF2-SHA256 con 600.000 iterazioni.
In alcune situazioni, potresti voler esportare tutte le password crittografate da Discourse e importarle in un altro sistema. Ad esempio, potresti essere in fase di migrazione dall’autenticazione integrata di Discourse a un sistema SSO personalizzato. Ricorda che è impossibile estrarre le password originali dal database, quindi il sistema di destinazione deve essere in grado di eseguire lo stesso algoritmo di hashing con gli stessi parametri.
I dati delle password sono archiviati nella tabella user_passwords, che contiene le colonne password_hash, password_salt e password_algorithm. La colonna password_algorithm memorizza l’intero prefisso dell’algoritmo PHC (ad esempio $pbkdf2-sha256$i=600000,l=32$), che può variare da utente a utente se il numero di iterazioni è stato aumentato nel tempo.
Puoi utilizzare Data Explorer per esportare le informazioni in un formato leggibile dal computer:
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
Questo esporterà i dati nel formato nativo di Discourse. Il salt è codificato in esadecimale e l’hash della password è anch’esso codificato in esadecimale.
Alcuni sistemi esterni supportano il formato stringa PHC, che mira a rappresentare l’output di una funzione di hashing delle password in modo indipendente dall’algoritmo. Per pbkdf2-sha256, questa stringa contiene il tipo di algoritmo, il numero di iterazioni, il salt codificato in base64 e l’hash codificato in base64. Fortunatamente, Postgres può gestire tutto questo per noi in una singola query.
Per generare stringhe PHC per ogni utente di Discourse, puoi utilizzare una query di Data Explorer come questa:
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
Se utilizzi Auth0, usa invece questa:
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
