55
تشکر

آموزش هش(Hash) کردن پسورد در PHP

آموزش هش(Hash) کردن پسورد در PHP

آموزش هش(Hash) کردن پسورد در PHP

این مطلب در دسته بندی مطالب پی اچ پی است. پی اچ پی را در اینجا دنبال کنید.

 

هش کردن چیست؟
هش کردن مفهوم جدیدی نیست. برای مدت زمان طولانی است که از این روش استفاده میشود. برای فهمیدن hashing درباره اثر انگشت فکر کنید. هر نفر یک اثر انگشت متمایز دارد. مشابه آن هر متنی میتواند با سایز مخصوص خودش یک اثر انگشت دیجیتالی داشته باشد که به آن hash میگویند(hash در زبان انگلیسی به معنای مخلوط است). یک الگوریتم hash خوب, الگوریتمی است که دو متن hash شده یکسانی وجود نداشته باشد.
 


روش هش کردن در PHP

الگوریتم های متفاوتی برای تولید یک متن به صورت hash شده وجود دارد. مشهورهای آنها عبارتند از: MD5, SHA1 و Bcrypt. همه اینها در PHP ساپورت میشوند.

کار را با استفاده از تابع md5() در PHP شروع میکنیم.

ابتدا خودتان فرمی را در یک صفحه با دو تکست باکس username و password بسازید و به این صفحه متصل کنید. همچنین در کد زیر اطلاعات دیتابیس خود را با کد زیر تطبیق دهید. همچنین نوع این فیلدها در دیتابیس باید از نوع text باشد.

$db = new PDO('mysql:host=localhost;dbname=test;charset=UTF8', 'root', '');

$username=$_POST['username'];
$password=$_POST['password'];
	
$password=md5($password);
	
$query="insert into users (username,password) values (:username,:password)";
$stmt=$db->prepare($query);
$stmt->execute(array(
	":username"=>$username,
	":password"=>$password
)) or die('Your Pass and Username not Register');
echo "Your Password and Username is Registered."

کد بالا پسورد گرفته شده از کاربر را به صورت hash تبدیل و در دیتابیس ذخیره میکند. حالا برای گرفتن یوزرنیم و پسورد از دیتابیس همین عمل باید برعکس تکرار شود.
به صورت زیر: ابتدا فرم جهت ورود کاربر ساخته سپس به صفحه زیر متصل کنید:

$db = new PDO('mysql:host=localhost;dbname=test;charset=UTF8', 'root', '');
$username=$_POST['username'];
$password=$_POST['password'];
	
$password=md5($password);
	
$query="select * from users where username=:username and password=:password";
	
$stmt=$db->prepare($query);
$stmt->execute(array(
	":username"=>$username,
	":password"=>$password
));
	
$row=$stmt->fetch();
echo "Your Username Equal to:".$row['username']." and Your Password Equal to:".$row['password']."";

در مثال بالا تابع md5() یک hash 128 بیتی تولید میکند. شما به راحتی میتوانید به جای md5() از sha1() استفاده کنید. این تابع یک hash 160 بیتی تولید میکند.
اگر شما با تابع md5() پسورد “aparnet” را به hash تبدیل کنید متن hash شده برابر با زیر خواهد بود:

22ebe55718b854ba953f1b9077176701

هیچ وقت یک پسورد را دوباره hash نکنید. اینکار به امنیت اضافه نمیکند بلکه پسورد را ضعیف و بدردنخور میکند. برای مثال سعی نکنید ابتدا پسورد را به ms5 تبدیل سپس به تابع sha1 بفرستید. اینکار امکان برخورد hash را افزایش میدهد.
 


رفتن به مرحله بعدی
محققان چندین عیب برای الگوریتم های sha1 و md5 پیداکرده اند. به همین دلیل برنامه های مدرن PHP از این دو تابع برای hash کردن استفاده نمیکنند. بلکه آنها از الگوریتم خانواده sha2 مانند sha256 یا sha512 استفاده میکنند. بر اساس اسمشان یکی hash 256 بیتی و دیگری hash 512 بیتی تولید میکنند. این تابع ها جدید تر و به طور قابل ملاحظه ای قویتر از md5 هستند. یکی از آنها افزایش تعداد بیت ها که کاهش برخوردها را دربردارد.

کد زیر نحوه استفاده از sha256 را نشان میدهد.

$password=hash(“sha256”,$password);

PHP تابع hash() را ارائه میدهد. آرگومان اول نام الگوریتم را میگیرد( شما میتوانید از الگوریتم های sha256 , sha512 , md5 , sha1 و دیگر الگوریتم های متداول استفاده کنید). آرگومان دوم هم متنی که قرار است تبدیل به hash شود.

اضافه کردن امنیت با استفاده از Salts
خب با استفاده از sha512 شما بیشترین امنیت را به پسورتان اضافه میکنید. اما اگر حمله کننده به دیتابیس از انواع الگوریتم ها برای برگرداندن پسورد شما استفاده کند میتواند پسوردها را به راحتی رمزگشایی کند.

راه حل استفاده از یک عدد تصادفی در تولید hash است که با آن salt میگویند. در هر بار که ما تولید hash میکنیم از یک عدد تصادفی استفاده میکنیم. شما فقط کافی است که یک عدد تصادفی در اندازه خاصی تولید و آن را به متن پسورد بدهید سپس آن را hash کنید.
حتی اگر پسورد دو اکانت شبیه هم باشد باز هم رشته hash شده شبیه هم نخواهد بود زیرا ما از عدد تصادفی استفاده میکنیم.
برای استفاده از salt مانند زیر عمل میکنیم:

define("MAX_LENGTH_SALT",6);
function generateHash($password){
    $rand=md5(uniqid(rand(),true));
    $salt=substr($rand , 0 , MAX_LENGTH_SALT);
    return hash("sha256",$password . $salt);
}

برای ساخت salt ما به uniqid() احتیاج داریم. آرگومان اول تابع rand است که یک عدد تصادفی در integer میسازد و آرگومان دوم true میگیرد زیرا ما میخواهیم اعداد منحصر به فرد باشند.

برای اعتبارسنجی کاربر باید مقدار salt را در ذخیره کنیم(در یکی از فیلدهای دیتابیس). زمانی که کاربر سعی کرد وارد اکانت خود شود مقدار salt را در پسورد وارد شده وارد میکنیم سپس با استفاده از تابع hash مقایسه را انجام میدهیم.
 


حتی بیشتر از این با Bcrypt
یادگرفتن درباره md5 و sha1 و salt برای فهم آنچه که مورد نیاز ما برای ذخیره سازی امن هست خوب است. اما برای اجرای شدید امنیت باید از تکنیک Bcrypt در hashing استفاده کنیم.
ما باید از یک الگوریتم استفاده کنیم که حمله کننده خیلی سخت بتواند آن را رمزگشایی کند و به راحتی بتوان از آن در اپلیکیشن ها استفاده کرد. اگر از Bcrypt استفاده کنیم لازم نیست دیگر salt را ذخیره کنیم.
مثال:

function generateHash($password){
    if(defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH){
        $salt='$2y$11$' . substr(md5(uniqid(rand(),true)),0,22);
        return crypt($password,$salt);
    }
}

تابع بالا ابتدا ثابت CRYPT_BLOWFISH را چک میکند. اگر این قابلیت وجود داشت یک salt تولید میکنیم. Salt تولید شده باید با “$2a$” یا “$2y$” شروع شده باشد. برای اطلاعات بیشتر در این مورد به PHP Manual مراجعه کنید.

برای شناسایی کاربر نیز از تابع زیر استفاده میکنیم. در صورت درست بودن, این تابع یک را برمیگرداند.

function verify($password,$hashedPassword){
    return crypt($password,$hashedPassword) == $hashedPassword;	
}
  • نیما می‌گه:

    Bcrypt روش خوبیه ولی اجرای کدش کنده نسب به اون یکی ها ، میدونم امنیت مهمه

    این روش رو شما پیشنهاد میکنین سرعتش به نسبت خوب بود سرعت اجرا

    $passwd = ‘2030’;
    $password = crypt($passwd);
    echo $password;

  • الهی پور می‌گه:

    با سلام و عرض خسته نباشید آقای شفیعی,
    امیدوارم در ادامه نیز مانند حال موفق باشید
    سوال من:اینکه در رمز دار کردن پسورد من از تابع MD5 در جدولم که درون دیتا بیس است استفاده کردم همچنین کدم هم به اینصورته
    $_pass=$_POST[“pass”]
    و کد اس کیو ال و بقیه کار اما بعد از وارد کردن نام کاربری و کلمه عبور خطای کلمه عبور اشتباه است نشان داده میشود که در صورتی که کلمه عبور اشتباه باشد نمایش داده میشود اما کلمه عبور درست وارد میشود لطفا راهنمایی کنید با تشکر.

  • yasairane2014 می‌گه:

    سلام استاد
    یک خواهشی داشتم می شود sample این اموزش را هم قرار بدهید که چونه می توانیم ازش استفاده کنیم هم ممنون می شوم
    چون باید پروژه دانشگاه را امده کنم دیگه آخرشم
    ممنون شما می شوم

    • محسن شفیعی می‌گه:

      اگه از BCrypt میخواهید استفاده کنید که به شدت توصیه میشه، فقط کافیه از دو تا تابع نوشته شده استفاده کنید.
      به تابع اولی میتونید که متن بدید و اون تابع هش شده اون رو میده.
      در تابع دومی میتونید یک متن هش نشده رو با متن هش شده قبلی برای مساوی بودن اونها بررسی کنید.

  • yasairane2014 می‌گه:

    سلام وقت شما بخیر باشه میشه بفرماید نحوه استفاده از این کد چطوری ؟

    define(“MAX_LENGTH_SALT”,6);
    function generateHash($password){
    $rand=md5(uniqid(rand(),true));
    $salt=substr($rand , 0 , MAX_LENGTH_SALT);
    return hash(“sha256″,$password . $salt);
    }

    باید یک فیلد دیگر بسازام درسته و چطوری آن وارد دیتابیس کنم
    ممنون می شوم یک توضیح کلی بفرماید با تشکر

  • amentaheri می‌گه:

    سلام میشه یه کم بیشتر توضیع بده من نکرفتم چه طور باید ازش استفاده کنم

  • Arya می‌گه:

    یکی پیدا نمیشه جواب منو بده ؟
    چطور میتونم اکانت فیسبوک رو هک کنم ؟

    • yasin می‌گه:

      اولین اینکه از مدیر تقاضای پوزش دارم دوما این تبلیغ نیست.محض اطلاع بیشتر میگم.
      میتونید برید تویwww.virus32.blog.ir اونجا توضیح داده شده.
      با تشکر…

  • Arya می‌گه:

    سلام ” با تشکر از سایت خوبتون .
    یه سوال داشتم .. چطور میشه اکانت فیس بوک رو
    هک کنم ؟

  • Arya می‌گه:

    slm ” ba tashakor az site xubetun.
    ye soal dashtam ” chetor mishe Accounte FB
    dustam ro ba estefade az in ravesh hack konam ?

  • یوسف شیری می‌گه:

    بسیار عالی!
    امیدوارم همیشه و در تمام مراحل زندگی موفق و پیروز باشید!

  • ali می‌گه:

    سلام ، مرسی از آموزشتون ، من یه سوال داشتم
    چطوری میتونم قسمت هایی از سرس php ام رو کد کنم جوری که دیده نشه ، md5 و sha on way hash هستند یعنی نمیشه متن هش شده رو به حالت اول برگرداند ، راه حل شما چیه؟

    • محسن شفیعی می‌گه:

      شما اصلا لازم نیست کدهای PHPتون رو کد کنید تا دیده نشه. چون اصلا کسی نمیتونه کدهای PHP شما رو ببینه. ولی اگه بازم میخواید اینکارو کنید عبارت php encode رو سرچ کنید.

  • علی می‌گه:

    با عرض تشکر بله این کار برای ارسال رمز جدید برای کاربری که رمز عبور را فراموش کرده جواب می ده ولی در cms ادمین سایت رمز اصلی یا decrypt شده را چگونه بفهمد.

  • علی می‌گه:

    باتشکر . اگه ممکنه decrypt کد آخر رو برای فراموشی رمز عبور بهم بگید. ممنون

    • محسن شفیعی می‌گه:

      زمانی که کاربر رمز را فراموش کرده است، به رمز قبلی احتیاجی ندارید. ابتدا کاربر درخواست بدست آوردن رمز را بوسیله دادن ایمیل خود میکند، سپس شما به ایمیل کاربر یک URL میفرستید که کاربر با کلیک کردن روی آن به یک صفحه از سایت شما می آید که در آنجا کاربر میتواند یک رمز عبور جدید برای خود انتخاب کند.
      فقط URL باید یکتا باشد و دارای یک عبارت هش شده تصادفی باشد که آن را باید در دیتابیس ذخیره کنید و زمانی که کاربر URL را باز کرد عبارت هش شده URL و عبارت هش شده در دیتابیس را مقایسه میکنید اگر درست بود یعنی این همان کاربر است.
      امیدوارم واضح بوده باشه.

  • محمود می‌گه:

    خوب اگر هکر بتواند به سورس سایت دسترسی پیدا کند و کلید را پیدا کند هش را راحت دیکد میکند
    md5 که یکی از راحت ترین هشها برای دیکد کردن است
    و نیازبه چیز خاصی ندارد!
    اینم به راحتی میشه دیکد کرد

    بهترین راه حل برای کد کردن هشها
    اینه که اگر اینها در دیتا بیس ذخیره میشوند با الگوریتمی خاص
    هش را چند تکه و در مکانهایی با نامهای غیر متعارف ذخیره کنیم
    اینطور شاید اونم شاید بشه از دست هکرها راحت شد

    • محسن شفیعی می‌گه:

      اگر از روش آخر استفاده کنیم به این دلیل که مقدار salt ذخیره نمیشود امنیت به شدت بالا میرود. و امکان بدست آوردن پسورد بدون حدس زدن آن خیلی سخت میشود.


  • نظرات این مطلب بسته است.