يمكن العثور على التفاصيل الحالية حول نظام تخزين كلمات مرور Discourse في discourse/docs/SECURITY.md at main · discourse/discourse · GitHub. وقت كتابة هذا النص، نستخدم PBKDF2-SHA256 مع 600,000 تكرار.
في بعض الحالات، قد ترغب في تصدير جميع كلمات المرور المشفرة من Discourse واستيرادها إلى نظام آخر. على سبيل المثال، قد تكون أنت تنتقل من المصادقة المدمجة في Discourse إلى نظام SSO مخصص. تذكر أنه من المستحيل استخراج كلمات المرور الأصلية من قاعدة البيانات، لذا يجب أن يكون نظامك الوجهة قادرًا على تشغيل خوارزمية التجزئة نفسها بنفس المعاملات.
يتم تخزين بيانات كلمة المرور في جدول user_passwords، الذي يحتوي على أعمدة password_hash، password_salt، و password_algorithm. يخزن عمود password_algorithm بادئة خوارزمية PHC الكاملة (مثل $pbkdf2-sha256$i=600000,l=32$)، والتي قد تختلف من مستخدم لآخر إذا تم زيادة عدد التكرارات بمرور الوقت.
يمكنك استخدام مستكشف البيانات لتصدير المعلومات بتنسيق قابل للقراءة بواسطة الحاسوب:
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
سيؤدي هذا إلى تصدير البيانات بتنسيق Discourse الأصلي. يتم ترميز الملح (salt) بصيغة سداسية عشرية (hex)، ويُرمَّز تجزئة كلمة المرور (password hash) أيضًا بصيغة سداسية عشرية.
تدعم بعض الأنظمة الخارجية تنسيق سلسلة PHC الذي يهدف إلى تمثيل مخرجات دالة تجزئة كلمات المرور بطريقة عابرة للخوارزميات. بالنسبة لـ pbkdf2-sha256، تحتوي هذه السلسلة على نوع الخوارزمية، وعدد التكرارات، والملح المشفر بترميز Base64، والتجزئة المشفرة بترميز Base64. لحسن الحظ، يمكن لـ Postgres التعامل مع كل ذلك في استعلام واحد.
لتوليد سلاسل PHC لكل مستخدم في Discourse، يمكنك استخدام استعلام مستكشف البيانات مثل هذا:
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
إذا كنت تستخدم Auth0، فستحتاج إلى هذا الاستعلام بدلاً من ذلك:
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