php - مقترحة - موقع انشاء كلمة مرور




تأمين التجزئة والملح لكلمات مرور PHP (10)

إخلاء المسؤولية : تمت كتابة هذه الإجابة في عام 2008.

منذ ذلك الحين ، أعطتنا PHP php.net/manual/en/function.password-hash.php password_verify ، ومنذ تقديمها ، فهي طريقة موصى بها لتجزئة كلمة المرور.

نظرية الجواب لا تزال قراءة جيدة رغم ذلك.

TL، DR

يترك

  • لا تحد ما الأحرف التي يمكن للمستخدمين إدخالها لكلمات المرور. فقط البلهاء يفعلون هذا
  • لا تحد من طول كلمة المرور. إذا كان مستخدموك يريدون جملة مع supercalifragilisticexpialidocious فيها ، فلا تمنعهم من استخدامها.
  • لا تقم أبدًا بتخزين كلمة مرور المستخدم الخاصة بك بنص عادي.
  • لا ترسل مطلقًا كلمة مرور إلى المستخدم إلا عندما يفقدون كلمة المرور الخاصة بهم ، وقمت بإرسال كلمة مرور مؤقتة.
  • أبدا ، من أي وقت مضى تسجيل كلمات المرور بأي شكل من الأشكال.
  • أبدا كلمات المرور تجزئة مع SHA1 أو MD5 أو حتى SHA256! يمكن أن تتجاوز المفرقعات الحديثة 60 و 180 مليار درهم / ثانية (على التوالي).
  • لا تخلط bcrypt ومع الإخراج الخام من hash () ، إما استخدام إخراج عرافة أو base64_encode عليه. (ينطبق هذا على أي إدخال قد يحتوي على \0 rogue \0 ، مما قد يؤدي إلى إضعاف الأمان بشكل خطير.)

دوس

  • استخدم scrypt عندما تستطيع ؛ bcrypt إذا كنت لا تستطيع ذلك.
  • استخدم PBKDF2 إذا كنت لا تستطيع استخدام bcrypt أو scrypt ، باستخدام SHA2 hashes.
  • إعادة تعيين كلمات مرور الجميع عند اختراق قاعدة البيانات.
  • تنفيذ الحد الأدنى للطول المناسب من 8 إلى 10 أحرف ، بالإضافة إلى تتطلب حرفًا كبيرًا واحدًا على الأقل ، وحرفًا صغيرًا واحدًا ، ورقمًا ، ورمزًا. سيؤدي ذلك إلى تحسين إنتروبيا كلمة المرور ، مما يجعل من الصعب كسرها. (راجع قسم "ما الذي يجعل كلمة مرور جيدة؟" في بعض النقاش.)

لماذا تجزئة كلمات المرور على أي حال؟

الهدف من وراء كلمات مرور التجزئة بسيط: منع الوصول الخبيث إلى حسابات المستخدمين من خلال تعريض قاعدة البيانات للخطر. لذا فإن الهدف من تجزئة كلمة المرور هو ردع أحد المتسللين أو المخترقين بتكلفتهم الكثير من الوقت أو المال لحساب كلمات المرور النصية العادية. والوقت / التكلفة هي أفضل رادع في ترسانتك.

سبب آخر أنك تريد تجزئة جيدة ، قوية على حسابات المستخدمين هو أن يمنحك الوقت الكافي لتغيير جميع كلمات المرور في النظام. إذا تم اختراق قاعدة البيانات الخاصة بك ، فسوف تحتاج إلى وقت كافٍ لإغلاق النظام على الأقل ، إذا لم يتم تغيير كل كلمة مرور في قاعدة البيانات.

صرح Jeremiah Grossman، CTO of Whitehat Security ، في مدونته بعد استعادة كلمة المرور الأخيرة التي تطلبت كسر القوة الغاشمة لحماية كلمة المرور الخاصة به:

من المثير للاهتمام ، في العيش خارج هذا الكابوس ، تعلمت الكثير وأنا لم أكن أعرف عن تكسير كلمة المرور ، والتخزين ، والتعقيد. جئت لتقدير سبب أهمية تخزين كلمات المرور أكثر من تعقيد كلمة المرور. إذا كنت لا تعرف كيف يتم تخزين كلمة المرور الخاصة بك ، فكل ما يمكنك الاعتماد عليه هو التعقيد. قد تكون هذه معرفة مشتركة بكلمة المرور ومحترفي التشفير ، ولكن بالنسبة لخبير InfoSec أو Web Security ، فإنني أشك بشدة في ذلك.

(التشديد لي.)

ما الذي يجعل كلمة مرور جيدة على أي حال؟

Entropy . (لا أوافق بالكامل على وجهة نظر راندال.)

باختصار ، فإن الإنتروبيا هي مقدار الاختلاف في كلمة المرور. عندما تكون كلمة المرور عبارة عن أحرف رومانية صغيرة فقط ، هذا فقط 26 حرفًا. هذا ليس كثير الاختلاف. وكلمات المرور الرقمية هي أفضل ، مع 36 حرفًا. لكن السماح بالحروف العلوية والسفلية ، بالرموز ، يبلغ 96 حرفًا تقريبًا. هذا أفضل بكثير من الرسائل. تتمثل إحدى المشاكل في جعل كلمات المرور الخاصة بنا لا تنسى ، حيث نقوم بإدخال الأنماط — مما يقلل من الانتروبيا. وجه الفتاة!

كلمة السر إنتروبيا approximated بسهولة. يؤدي استخدام مجموعة كاملة من أحرف ascii (حوالي 96 حرفًا قابلاً للطباعة) إلى إنتروبيا تبلغ 6.6 حرفًا لكل حرف ، والتي لا تزال عند 8 أحرف لكلمة مرور منخفضة جدًا (52.679 بت من الإنتروبيا) للأمان المستقبلي. لكن الخبر السار هو: كلمات مرور أطول وكلمات مرور بأحرف unicode ، تزيد من حقيقة كلمة السر وتجعل من الصعب كسرها.

هناك مناقشة أطول للانتروبيا كلمة المرور على موقع Crypto StackExchange . سيحقق البحث الجيد من Google أيضًا الكثير من النتائج.

في التعليقات التي تحدثت معها معpopnoodles ، الذي أشار إلى أن تطبيق سياسة كلمة مرور X مع X العديد من الحروف والأرقام والرموز وغيرها ، يمكن في الواقع أن يقلل من الانتروبيا عن طريق جعل مخطط كلمة المرور أكثر قابلية للتنبؤ. أنا أوافق إن العشوائية ، كعشوائية ممكنة قدر الإمكان ، هي دائمًا الحل الأكثر أمانًا ولكنه لا يُنسى.

بقدر ما كنت قادرا على إخباره ، فإن جعل أفضل كلمة مرور في العالم هو Catch-22. إما الأحرف التي لا تنسى أو يمكن التنبؤ بها أو قصيرة جدًا أو عددًا كبيرًا من أحرف unicode (يصعب كتابتها على جهاز Windows / Mobile) ، أو طويلة جدًا ، وما إلى ذلك. لا توجد كلمة مرور جيدة بما يكفي لأغراضنا ، لذلك يجب أن نحميهم كما لو كانوا كانت في فورت نوكس.

أفضل الممارسات

Bcrypt و scrypt هي أفضل الممارسات الحالية. سيكون scrypt أفضل من bcrypt في الوقت المناسب ، لكنه لم ير التبني كمعيار من قبل Linux / Unix أو من قبل خوادم الويب ، ولم يقم بمراجعة متعمقة لخوارزمية نشرها حتى الآن. ولكن لا يزال ، مستقبل الخوارزمية يبدو واعدًا. إذا كنت تعمل مع Ruby ، ​​فهناك جوهرة مقفلة ستساعدك على الخروج ، ولدى Node.js الآن حزمة scrypt خاصة بها. يمكنك استخدام Scrypt in PHP إما عن طريق امتداد Scrypt أو ملحق Libsodium (يتوفر كلاهما في PECL).

أقترح بشدة قراءة وثائق وظيفة القبو إذا كنت تريد فهم كيفية استخدام bcrypt ، أو العثور على wrapper good أو استخدام شيء مثل openwall.com/phpass لتنفيذ أكثر تراثًا. أوصي بحد أدنى 12 جولة من bcrypt ، إن لم يكن 15 إلى 18.

لقد غيرت رأيي في استخدام bcrypt عندما علمت أن bcrypt يستخدم فقط الجدول الزمني الرئيسي blowfish ، مع آلية التكلفة المتغيرة. هذا الأخير يتيح لك زيادة تكلفة القوة الغاشمة لكلمة المرور عن طريق زيادة الجدول الزمني الرئيسي مكلف بالفعل.

متوسط ​​الممارسات

أنا تقريبا لا أستطيع تخيل هذا الموقف بعد الآن. يدعم openwall.com/phpass PHP 3.0.18 من خلال 5.3 ، لذلك فهو قابل للاستخدام على كل تركيب تقريباً يمكن تخيله - ويجب استخدامه إذا كنت لا تعرف على وجه اليقين أن بيئتك تدعم bcrypt.

ولكن لنفترض أنك لا تستطيع استخدام bcrypt أو PHPASS على الإطلاق. ماذا بعد؟

حاول تنفيذ PDKBF2 مع الحد الأقصى لعدد الجولات التي يمكن أن تتحملها بيئة / تطبيق / إدراك المستخدم. أقل عدد نوصي به هو 2500 طلقة. أيضًا ، تأكد من استخدام hash_hmac() إذا كان متاحًا لجعل العملية أكثر صعوبة في التكاثر.

الممارسات المستقبلية

المجيء في PHP 5.5 هو مكتبة حماية بكلمة مرور تزيل أي آلام للعمل مع bcrypt. في حين أن معظمنا عالقون مع PHP 5.2 و 5.3 في أكثر البيئات شيوعًا ، خاصةً المضيفات المشتركة ، فقد قامircmaxell ببناء طبقة توافق لواجهة برمجة التطبيقات (API) القادمة المتوافقة للخلف مع PHP 5.3.7.

تشفير وإخلاء المسؤولية

لا توجد القدرة الحسابية اللازمة لكسر كلمة مرور مجزأة. الطريقة الوحيدة لأجهزة الكمبيوتر "لكسر" كلمة مرور هي إعادة إنشائها ومحاكاة خوارزمية التجزئة المستخدمة لتأمينها. ترتبط سرعة التجزؤ خطيًا بقدرتها على أن تكون قسرية. الأسوأ من ذلك ، يمكن لمعظم خوارزميات التجزئة موازية بسهولة لأداء أسرع. هذا هو السبب في مخططات مكلفة مثل bcrypt و scrypt في غاية الأهمية.

لا يمكنك توقع كل التهديدات أو طرق الهجوم ، ولذلك يجب عليك بذل قصارى جهدك لحماية مستخدميك في المقدمة . إذا لم تقم بذلك ، فقد تفوت حتى حقيقة أنك تعرضت للهجوم حتى فوات الأوان ... وأنت مسؤول . لتجنب هذا الوضع ، اعمل بجنون العظمة لتبدأ. قم بتوجيه البرامج الخاصة بك (داخليًا) ومحاولة سرقة بيانات اعتماد المستخدم أو تعديل حسابات المستخدمين الآخرين أو الوصول إلى بياناتهم. إذا لم تختبر أمان النظام الخاص بك ، فلا يمكنك إلقاء اللوم على أي شخص سوى نفسك.

أخيرا: أنا لست مشفرة. كل ما قلته هو رأيي ، لكني أعتقد أنه يعتمد على الحس السليم "الحس السليم ... والكثير من القراءة. تذكر ، كن متذمرا قدر الإمكان ، اجعل الأشياء أكثر صعوبة في التطفل قدر الإمكان ، وبعد ذلك ، إذا كنت لا تزال قلقا ، اتصل بهاكر القبعة البيضاء أو عالم التشفير لمعرفة ما يقولونه عن الكود / النظام الخاص بك.

يقال حاليا أن MD5 غير آمن بشكل جزئي. مع أخذ ذلك في الاعتبار ، أود معرفة الآلية التي يجب استخدامها لحماية كلمة المرور.

هذا السؤال ، هل "تجزئة مزدوجة" كلمة مرور أقل أمانًا من تجزئتها مرة واحدة فقط؟ تشير إلى أن التجزئة عدة مرات قد تكون فكرة جيدة ، في حين أن كيفية تنفيذ حماية كلمة المرور للملفات الفردية؟ يقترح استخدام الملح.

أنا أستخدم PHP. اريد نظام تشفير كلمات مرور سريع وآمن. قد يكون تجزئة كلمة المرور مليون مرة أكثر أمانًا ، ولكن أيضًا بشكل أبطأ. كيف نحقق توازنا جيدا بين السرعة والسلامة؟ أيضا ، أنا أفضل النتيجة أن يكون هناك عدد ثابت من الأحرف.

  1. يجب أن تكون آلية التجزئة متاحة في PHP
  2. يجب أن تكون آمنة
  3. يمكن أن يستخدم الملح (في هذه الحالة ، هل جميع الأملاح جيدة على حد سواء؟ هل هناك أي طريقة لتوليد أملاح جيدة؟)

أيضاً ، هل يجب تخزين حقلين في قاعدة البيانات (واحد باستخدام MD5 وآخر باستخدام SHA ، على سبيل المثال)؟ هل ستجعله أكثر أمنا أم لا؟

في حالة لم أكن واضحًا بما فيه الكفاية ، أريد معرفة وظيفة (وظائف) التجزئة وكيفية اختيار الملح الجيد من أجل الحصول على آلية آمنة وسريعة لحماية كلمة المرور.

الأسئلة ذات الصلة التي لا تغطي سؤالي تمامًا:

ما الفرق بين SHA و MD5 في PHP
تشفير كلمة مرور بسيطة
طرق آمنة لتخزين المفاتيح وكلمات المرور ل asp.net
كيف يمكنك تنفيذ كلمات المرور المملحة في Tomcat 5.5


أريد فقط الإشارة إلى أن PHP 5.5 يشتمل على واجهة برمجة تطبيقات تجزئة كلمة مرور توفر غلافًا حول crypt() . تعمل واجهة برمجة التطبيقات هذه على تبسيط مهمة التجزئة ، والتحقق من وتكرار تجزئات كلمات المرور. أصدر المؤلف أيضًا حزمة توافق (على شكل ملف password.php واحد require إلى استخدامه ببساطة) ، لأولئك الذين يستخدمون PHP 5.3.7 وما بعده ويريدون استخدام هذا الآن.

إنه يدعم BCRYPT فقط في الوقت الحالي ، ولكنه يهدف إلى أن يتم توسيعه بسهولة ليشمل تقنيات التجزئة الأخرى لكلمة المرور ولأن التقنية والتكلفة يتم تخزينها كجزء من التجزئة ، فإن التغييرات على تقنية التجزئة المفضلة لديك / التكلفة لن تبطل التجزئات الحالية ، الإطار ستقوم تلقائيًا باستخدام التقنية / التكلفة الصحيحة عند التحقق من الصحة. كما أنه يعالج توليد ملح "آمن" إذا لم تقم بتعريف حسابك بشكل صريح.

تعرض واجهة برمجة التطبيقات أربعة وظائف:

  • password_get_info() - يعرض معلومات حول التجزئة المعطاة
  • password_hash() - يخلق تجزئة كلمة المرور
  • password_needs_rehash() - للتحقق من تطابق التجزئة المعطاة مع الخيارات المحددة. مفيد لمعرفة ما إذا كان التجزئة يتوافق مع نظامك الحالي للتكلفة / التقنية مما يسمح لك بإعادة التلاعب إذا لزم الأمر
  • password_verify() - يتحقق من أن كلمة المرور تطابق التجزئة

في الوقت الحالي ، تقبل هذه الوظائف ثوابت كلمة المرور PASSWORD_BCRYPT و PASSWORD_DEFAULT ، والتي هي مرادفة في الوقت الحالي ، والفرق هو أن PASSWORD_DEFAULT "قد يتغير في إصدارات PHP الأحدث عندما تكون خوارزميات التجزئة الأحدث والأقوى مدعومة." يجب أن يضمن استخدام PASSWORD_DEFAULT و password_needs_rehash () عند تسجيل الدخول (وإعادة الصياغة إذا لزم الأمر) أن تكون علامات التجزئة الخاصة بك مرنة بشكل معقول لهجمات القوة الغاشمة مع القليل من العمل بدون عمل.

تحرير: لقد أدركت للتو أن هذا مذكور بإيجاز في إجابة روبرت ك. سأترك هذه الإجابة هنا لأنني أعتقد أنها توفر المزيد من المعلومات حول كيفية عملها وسهولة الاستخدام التي توفرها لأولئك الذين لا يعرفون الأمن.


اعتبارا من PHP 5.5 ، PHP لديه وظائف بسيطة وآمنة لتجزئة والتحقق من كلمات المرور ، php.net/manual/en/function.password-hash.php و password_verify

$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false

عند استخدام password_hash() ، يقوم بإنشاء ملح عشوائي وتضمينه في تجزئة الإخراج (جنبا إلى جنب مع التكلفة والخوارزمية المستخدمة.) password_verify() ثم يقرأ ذلك التجزئة ويحدد طريقة الملح والتشفير المستخدمة ، ويتحقق منها مقابل كلمة مرور النص العادي المقدمة.

يوفر إرشاد PASSWORD_DEFAULT PHP لاستخدام خوارزمية التجزئة الافتراضية للإصدار المثبت من PHP. بالضبط أي خوارزمية يعني أن المقصود أن تتغير بمرور الوقت في الإصدارات المستقبلية ، بحيث تكون دائما واحدة من أقوى الخوارزميات المتاحة.

إن زيادة التكلفة (التي تصل إلى 10 مرات) تجعل التجزئة أكثر صعوبة في القوة العنيفة ، ولكنها تعني أيضًا أن توليد علامات التجزئة والتحقق من كلمات المرور ضدها ستؤدي إلى مزيد من العمل لوحدة المعالجة المركزية لخادمك.

لاحظ أنه على الرغم من أن خوارزمية التجزئة قد تتغير ، فإن التجزئات القديمة ستستمر في التحقق من الصواب لأن الخوارزمية المستخدمة مخزنة في البعثرة و password_verify() تلتقطها.


جواب أقصر وأكثر أمانًا - لا تكتب آلية كلمة المرور الخاصة بك على الإطلاق ، استخدم آلية مجربة ومختبرة.

معظم المبرمجين لا يمتلكون الخبرة الكافية لكتابة التعليمات البرمجية ذات الصلة بأمان دون تقديم نقاط ضعف.

اختبار ذاتي سريع: ما هو امتداد كلمة المرور وعدد التكرارات التي ينبغي لك استخدامها؟ إذا كنت لا تعرف الإجابة ، فيجب عليك استخدام password_hash() ، حيث أن تمديد كلمة المرور أصبح الآن ميزة حاسمة لآليات كلمة المرور بسبب وجود وحدات معالجة مركزية أسرع بكثير واستخدام GPU و FPGA لكسر كلمات المرور بمعدلات مليارات التخمينات في الثانية (مع GPUs).

على سبيل المثال ، يمكنك كسر كلمات مرور Windows المكونة من 8 أحرف في 6 ساعات باستخدام 25 وحدة معالجة الرسومات مثبتة في 5 أجهزة كمبيوتر سطح مكتب. هذا هو فرض brute أي ie وفحص كل كلمة مرور Windows 8 أحرف ، بما في ذلك الأحرف الخاصة وهو ليس هجوم القاموس. كان ذلك في عام 2012 ، واعتبارًا من عام 2018 ، كان بإمكانك استخدام عدد أقل من وحدات معالجة الرسومات ، أو الكراك بشكل أسرع باستخدام 25 وحدة معالجة الرسومات.

هناك أيضا العديد من هجمات جدول قوس قزح على كلمات مرور Windows التي تعمل على وحدات المعالجة المركزية العادية وهي سريعة جدا. كل هذا لأن Windows لا يزال غير ملح أو يمدد كلمات المرور الخاصة به ، حتى في Windows 10 - لا ترتكب نفس الخطأ كما فعلت Microsoft!

أنظر أيضا:

  • إجابة ممتازة مع مزيد من المعلومات حول سبب أن password_hash() أو phpass هي أفضل طريقة للذهاب.
  • جيدة مقال بلوق إعطاء 'عوامل العمل' الموصى بها (عدد التكرارات) للخوارزميات الرئيسية بما في ذلك bcrypt ، scrypt و PBKDF2.

على الرغم من الإجابة على السؤال ، أريد فقط التأكيد على أن الأملاح المستخدمة للتجزئة يجب أن تكون عشوائية وليست مثل عنوان البريد الإلكتروني كما هو مذكور في الإجابة الأولى.

يتوفر المزيد من الشرح على http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

لقد أجريت مؤخراً مناقشة حول ما إذا كان تجزئة كلمات المرور المملحة مع البتات العشوائية أكثر أمانًا من تلك المملحة بأملاح معروفة أو معروفة. دعونا نرى: إذا تم اختراق نظام تخزين كلمة المرور وكذلك النظام الذي يخزن الملح العشوائي ، فإن المهاجم سيكون لديه حق الوصول إلى التجزئة وكذلك الملح ، لذلك سواء كان الملح عشوائيا أم لا ، لا يهم. يمكن للمهاجم إنشاء جداول قوس قزح محسوبة مسبقًا للقضاء على التجزئة. هنا يأتي الجزء المثير للاهتمام - ليس من السهل جدا لتوليد الجداول المحسوبة مسبقا. دعونا نأخذ مثالا على نموذج أمن WPA. لم يتم إرسال كلمة مرور WPA الخاصة بك إلى نقطة الوصول اللاسلكية. بدلا من ذلك ، يتم تجزئته مع SSID الخاص بك (اسم الشبكة - مثل لينكسيس ، Dlink الخ). شرح جيد جدا لكيفية عمل هذا هنا. لاستعادة كلمة المرور من التجزئة ، ستحتاج إلى معرفة كلمة المرور بالإضافة إلى الملح (اسم الشبكة). قامت بالفعل "كنيسة واي فاي" بالفعل بحساب جداول هاش التي تحتوي على 1000 من SSIDs وحوالي مليون كلمة مرور. الحجم من جميع الجداول حوالي 40 جيجابايت. كما يمكنك القراءة على موقعهم ، استخدم شخص ما 15 صفيفًا FGPA لمدة 3 أيام لإنشاء هذه الجداول. بافتراض أن الضحية تستخدم SSID كـ "a387csf3" وكلمة المرور على أنها "123456" ، هل سيتم تصدعها بتلك الجداول؟ لا! .. لا تستطيع. حتى إذا كانت كلمة المرور ضعيفة ، لا تحتوي الجداول على تجزئة لـ SSID a387csf3. هذا هو جمال وجود الملح العشوائي. وسوف تردع المفرقعات التي تزدهر على الجداول المحسوبة مسبقا. هل يمكنه إيقاف أي هاكر محدد؟ على الاغلب لا. ولكن استخدام الأملاح العشوائية يوفر طبقة إضافية من الدفاع. بينما نحن في هذا الموضوع ، دعونا نناقش ميزة إضافية لتخزين الأملاح العشوائية على نظام منفصل. السيناريو الأول: يتم تخزين تجزئات كلمة المرور على النظام X ويتم تخزين قيم الملح المستخدمة في التجزئة على النظام Y. تكون قيم الملح هذه قابلة للتخمين أو معروفة (على سبيل المثال اسم المستخدم) السيناريو الثاني: يتم تخزين تجزئات كلمات المرور على النظام X وقيم الملح المستخدمة يتم تخزين التجزئة على نظام Y. هذه القيم الملح عشوائية. في حالة اختراق النظام X ، كما يمكنك التخمين ، هناك ميزة كبيرة لاستخدام الملح العشوائي في نظام منفصل (السيناريو 2). سيحتاج المهاجم إلى تخمين قيم الإضافة ليتمكن من التخلص من التجزئات. إذا تم استخدام ملح 32 بت ، فسيتم طلب 2 ^ 32 = 4،294،967،296 (حوالي 4.2 مليار) لكل كلمة مرور.


في النهاية ، التجزئة ، رياضيا ، لا تقدم أي فائدة. في الممارسة العملية ، ومع ذلك ، فإنه من المفيد لمنع الهجمات على أساس قوس قزح الجدول. وبعبارة أخرى ، فإنه ليس أكثر فائدة من التجزئة مع الملح ، والتي تأخذ وقت أقل بكثير من المعالج في التطبيق الخاص بك أو على الخادم الخاص بك.


لقد وجدت موضوعًا مثاليًا في هذه المسألة هنا: https://crackstation.net/hashing-security.htm ، أردت منك أن تستفيد منه ، إليك شفرة المصدر أيضًا التي وفرت الوقاية ضد الهجوم المستند إلى الوقت أيضًا.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

SHA1 and a salt should suffice (depending, naturally, on whether you are coding something for Fort Knox or a login system for your shopping list) for the foreseeable future. If SHA1 isn't good enough for you, use SHA256 .

The idea of a salt is to throw the hashing results off balance, so to say. It is known, for example, that the MD5-hash of an empty string is d41d8cd98f00b204e9800998ecf8427e . So, if someone with good enough a memory would see that hash and know that it's the hash of an empty string. But if the string is salted (say, with the string " MY_PERSONAL_SALT "), the hash for the 'empty string' (ie " MY_PERSONAL_SALT ") becomes aeac2612626724592271634fb14d3ea6 , hence non-obvious to backtrace. What I'm trying to say, that it's better to use any salt, than not to. Therefore, it's not too much of an importance to know which salt to use.

There are actually websites that do just this - you can feed it a (md5) hash, and it spits out a known plaintext that generates that particular hash. If you would get access to a database that stores plain md5-hashes, it would be trivial for you to enter the hash for the admin to such a service, and log in. But, if the passwords were salted, such a service would become ineffective.

Also, double-hashing is generally regarded as bad method, because it diminishes the result space. All popular hashes are fixed-length. Thus, you can have only a finite values of this fixed length, and the results become less varied. This could be regarded as another form of salting, but I wouldn't recommend it.


I usually use SHA1 and salt with the user ID (or some other user-specific piece of information), and sometimes I additionally use a constant salt (so I have 2 parts to the salt).

SHA1 is now also considered somewhat compromised, but to a far lesser degree than MD5. By using a salt (any salt), you're preventing the use of a generic rainbow table to attack your hashes (some people have even had success using Google as a sort of rainbow table by searching for the hash). An attacker could conceivably generate a rainbow table using your salt, so that's why you should include a user-specific salt. That way, they will have to generate a rainbow table for each and every record in your system, not just one for your entire system! With that type of salting, even MD5 is decently secure.


ok in the fitsy we need salt salt must be unique so let generate it

   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }

also we need the hash I`m using sha512 it is the best and it is in php

   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }

so now we can use this functions to generate safe password

// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);

now we need to save in database our $hash_psw variable value and $salt variable

and for authorize we will use same steps...

it is the best way to safe our clients passwords...

Ps for last 2 steps you can use your own algorithm... but be sure that you can generate this hashed password in the future when you need to authorize user...





protection