آموزش الگوریتم های رمزنگاری در php

  • آپدیت شده در تاریخ

آموزش الگوریتم های رمزنگاری در php

بروزرسانی در تاریخ ۵ آذر ۱۳۹۷

امروزه باتوجه به فراگیری اینترنت و قرار گیری اطلاعات سازمان ها و شرکت های کوچک و بزرگ برروی بانک های اطلاعاتی سایت و پرتال های  خود و دسترسی به اطلاعات به صورت طبقه بندی شده باتوجه به سطح و … محافظت از آنها بسیار حائز اهمیت بوده تا حدی که در سازمانهای متوسط و بزرگ بخشی به نام امنیت اطلاعات تشکیل شده است.

به دلیل محبوبیت زبان برنامه نویسی php  بسیاری از سایت ها و پرتال های بزرگ و کوچک با این زبان نوشته و ایجاد شده اند و ما قصد داریم که شیوه ها و اصول و الگوریتم های رمزنگاری در php  را در مقاله آموزش دهیم.

هش و رمزنگاری اطلاعات

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

تابع های معروف هش

تابع md5

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

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

توجه کنید که که متغیر ها هرچیزی میتوانند باشند هش فقط نام روش است.

با اینکه به این نتیجه رسیدیم که تابع md۵ از امنیت بالایی برخوردار نمیباشد اما نگران نباشید چون php  در نسخه ی ۵ به بالا از تابع های crypt و password_hash  پشتیبانی میکند که مراتب از تابع md۵ از امنیت بیشتری برخوردارند.

تابع crypt

این تابع از تابع md۵ از امنیت بالاتری برخوردار است و خود تابع کلمه ی اضافی (salt) رندوم را اضافه میکند.توجه کنید که این تابع در نسخه های ۵ به بعد php  میتوان به صورت ۲ پارامتری نوشت و salt  به عنوان پارامتر دوم قرار گیرد.

ویا به صورت زیر که از شرط if نیز استفاده شده است.

دقت کنید فقط دز نسخه های php ۵ به بالا تابع crypt میتواند دو متغیر را بپذیرد و در نسخه های پایین تر salt  را نمیتوانیم به عنوان متغیر دوم تابع در نظر بگیریم.

تابع password_hash

کد بالا به این صورت است که ابتدا مقدار داده شده توسط تابع password_hash هش میشود و توسط دستور شرطی if  درستی کمه ی عبور وارد شده بررسی میشود.

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

هش قابل بازگشت نیست یعنی اگر اطلاعات و داده های شما نیاز به بازیابی ندارند میتوانید برای افزایش امنیت اطلاعات از هش و قواعد رمزنگاری در چهارچوب هش استفاده نمایید.

برای استفاده از الگوریتم های رمزنگاری در php میتوانید از تابع هایی ابتدایی مانند base۶۴_encode و نیز در سطح بالاتر از تابع mcrypt_decrypt استفاده نمایید که در ادامه توضیح خواهیم داد.

تابع base۶۴_decode 

یکی از ساده ترین تابع هایی است که برای رمز نگاری استفاده میشود که با تابع base۶۴_encode قابل بازگشت است.

و مقدار بازگشتی آن به صورت زیر است:

توجه کنید که رای کدگشایی اطلاعات(اطلاعاتی که قبلا کدگذاری شده‌اند) از تابع base۶۴_decode استفاده می‌کنیم.در واقع تابع بالا مقدار بازگشتی تابع base۶۴_decode  می باشد.در مقاله آموزشی الگوریتم های رمزنگاری در php ، به هیچ وجه توصیه نمی شود که از این تابع برای رمزنگاری پسوردها استفاده کنید و این قسمت طرفا یک نوع معرفی است.

تابع mcrypt_encrypt

 یکی از بهترین توابع الگوریتم های رمزنگاری در php است که از الگوریتم MCRYPT_BLOWFISH بهره می برد که یکی از بهترین الگوریتم های رمزنگاری محسوب می شود ، به این صورت که یک رشته را بر اساس کلیدی که برای آن تعریف میکنیم ، رمز و سپس توس تابع بازگشت آن یعنی mcrypt_decrypt بازگشایی میکند.

بروزرسانی :

توابع زیرمجموعه mcrypt_ در نسخه php 7.1 منسوخ اعلام شده و  شما با خطای Deprecated مواجه می شوید و در نسخه های ۷٫۱ به بعد هم این تابع کاملا حذف شده و خطای Undefined Function نمایش داده می شود.

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

مثال زیر نحوه استفاده از این تابع برای اینکریپت و دی-کریپت را نشان می دهد :

نحوه استفاده از تابع :

 

توصیه ما این است که برای رمزنگاری در php از توایع غیرقابل برگشت مثل hash , md5 و الگوریتم های sha1 استفاده کنید تا امنیت رمزهای عبور شما حتی با لو رفتن دیتابیس به هر روشی مثل sql injection افشا و اطلاعات اکانت کاربران در اختیار افراد قرار نگیرد.

موفق و پیروز باشید.

حسن شفیعی توسعه دهنده وب و موبایل مدیر سایت علاقه خاصی به برنامه نویسی وب و موبایل دارم و هر روز تلاش می کنم به این حوزه مسلط تر شوم و اطلاعاتم را به شکل کاربردی برای علاقه مندان در وب به اشتراک بگذارم. اگر نیاز به برنامه نویس برای انجام پروژه و نوشتن اسکریپت های سمت وب, اپلیکیشن های اندروید و ios, پیدا کردن راه حل توسعه و غیره داشتید حتما از طریق تماس با ما/ واتساپ/ تلگرام بهم پیام بدید. برایتهیه هاست مطمین و پرسرعت کلیک کنید
مطالب زیر را حتما بخوانید
دیدگاه کاربران (۳۷)

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

  1. morteza ۹ بهمن ۱۴۰۲

    عااالی بووود مررررسی

    پاسخ
  2. سامان ۷ آبان ۱۴۰۱

    سلام و احترام
    من در نظر دارم به شخص دیگری اجازه بدهم به سی پانل دسترسی داشته باشد ولی صرفا به دیتابیس (mysql) آن دسترسی داشته باشد و متن برنامه در دسترس وی قرار نگیرد . آیا راهکاری در این مورد دارید؟ آیا امکان دارد در سی پانل فایلهای برنامه برای یک کاربر خاص نمایش داده نشود؟ یا مثلا اینکه برای نمایش فایلهای سورس برنامه نیاز به رمز خاصی باشد؟ ممنونم ازهمکاری شما

    پاسخ
    1. حسن شفیعی ۷ آبان ۱۴۰۱

      سلام.
      این رو از خود هاستینگ بپرسید که برای دسترسی دادن به فقط mysql چه کاری باید انجام بدید تا راهنماییتون کنن

      پاسخ
  3. ابوالفضل ۲۲ مهر ۱۴۰۱

    سلام وقت بخیر
    مقالتون عالی بود ولی میشه یکم بیشتر درباره openssl توضیح بدید. هر سایتی را که خوندم آخر نفهمیدم.

    پاسخ
    1. حسن شفیعی ۲۳ مهر ۱۴۰۱

      سلام. ممنون.
      خوشحالیم که مفید واقع شده.
      دقیقا مثل تابع mcrypt عمل میکنه و از الگوریتم رمزنگاری مشابه در بروتکل ssl استفاده میکنه و برای همین امنیت کلیدهایی که با این تابع تولید می کنید بالاست. برای همین توصیه میشه از همان مثالی که در اخر این مقاله قرار دادیم استفاده کنید و اگر میخواید درک عمیقی از عملکرد تابع داشته باشید حتما لینک تابع در سایت php.net رو به همراه کامنت هایی که براش گذاشتند رو مطالعه کنید

      پاسخ
      1. ابوالفضل ۲۷ مهر ۱۴۰۱

        من متوجه کاربرد $iv نشدم

        پاسخ
      2. حسن شفیعی ۲۸ مهر ۱۴۰۱

        سلام
        برای الگوریتم رمزنگاری AES-256-CBC باید یه کد سکرت به نام iv رو بدید

        پاسخ
      3. ابوالفضل ۲۸ مهر ۱۴۰۱

        یعنی در واقع برای رمزگشایی به دو پسورد نیاز داریم؟
        الگوریتم رمزنگاری AES-256-CBC ایمن هست؟

        پاسخ
      4. حسن شفیعی ۲۹ مهر ۱۴۰۱

        بله
        بله ایمن هست

        پاسخ
  4. محمود رنجبر ۱۲ بهمن ۱۴۰۰

    سلام مهندس شفیعی اگر هکر دو پسورد رو برگردونه وبا هم مقایسه کنه مقدار نمک رو تشخیص میده درسته ؟
    و اینکه میگن password_hash باعث میشه برای یک رشته در زمان های مختلف هش های مختلف تولید بشه وقتی میخوایم پسورد رو اعتبار سنجی کنیم با تابع password_verify مشکل پیش نمیاد میشه توضیحی بفرمائید سپاس از راهنمایی تون موفق باشید

    پاسخ
    1. حسن شفیعی ۱۲ بهمن ۱۴۰۰

      سلام. نه امنیتش بالا هست و هیچ مشکلی پیش نمیاد و همیشه هم درست تشخیص میده نگرانش نباشید

      پاسخ
  5. رضا راد ۲ تیر ۱۴۰۰

    سلام
    خیلی ممنونم از لطفتتون بابت این همه مقاله جذاب

    در خط زیر “تابع mcrypt_encrypt” غلط املایی دارید نوشتید بهرو

    پاسخ
    1. حسن شفیعی ۲ تیر ۱۴۰۰

      سلام. خوشحالیم که مفید واقع شده. متن اصلاح شد. موفق باشید.

      پاسخ
  6. فرزاد ۱۰ فروردین ۱۳۹۹

    سلام و تشکر از آموزش های عالی تون
    یه سوال ازاین میشه بجای JWT استفاده کرد برای امنیت لاگین و چک کردن؟
    چون JWT رو هر چی مطلاعه کردم نتونستم سر در بیارم واقعیت آموزش ۰ تا ۱۰۰ هم چیزی پیدا نکردم

    پاسخ
    1. حسن شفیعی ۱۰ فروردین ۱۳۹۹

      سلام. خوشحالیم که مفید واقع شده.
      بله میتونید از این مورد هم استفاده کنید و مشکلی نیست.
      موفق باشید.

      پاسخ
  7. امین ۳ آذر ۱۳۹۸

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

    پاسخ
    1. حسن شفیعی ۶ آذر ۱۳۹۸

      سلام. ممنون خوشحالیم که مفید واقع شده.
      باید از رمزنگاری های دو طرفه مثل openssl استفاده کنید تا بتونید این کار رو انجام بدید که در آخر همین پست به جای mcrypt در ورژن جدید php معرفی شده
      موفق باشید.

      پاسخ
  8. امیر ۳ مرداد ۱۳۹۸

    سلام
    بین اینا کدوم بهتر است:
    md5
    sha1
    sha256
    sha384
    sha512
    و اینکه با هم استفاده کنیم خوبه؟
    مثل کد زیر:
    function HashPassword( $pw ) {
    for($i = 0; $i < 40000; $i++) {
    $pw = md5(md5(md5(base64_encode($pw . $pw . 'veteran' . $i) . $pw . $i * 5000 . md5($i))));
    }
    return $pw;
    }

    پاسخ
    1. حسن شفیعی ۳ مرداد ۱۳۹۸

      سلام. سری sha بهتر هست و ترکیبی هم اوکی هست و مشکلی نیست میتونید استفاده کنید.
      موفق باشید.

      پاسخ
  9. محمد جواد ۱۰ اردیبهشت ۱۳۹۸

    سلام . قسمتی که کد مربوط به openssl_encrypt رو به عنوان نمونه قرار دادین salt رو باید کجای کد اضافه کرد ؟

    پاسخ
    1. محمد جواد ۱۰ اردیبهشت ۱۳۹۸

      ممنون میشم یه نگاه هم به این نمونه کدی که لینکشو میزارم بکنید و بررسیش کنید
      https://stackoverflow.com/a/46872528/388994

      پاسخ
      1. حسن شفیعی ۱۱ اردیبهشت ۱۳۹۸

        سلام. همان روشی که معرفی کردیم است و فقط یک تابع بیشتر به نام hash_hmac را استفاده کردند.
        همین تابعی که قرار دادیم کار شما را راه می اندازد و نیاز به پیچیده کردن تابع نیست چرا که رشته اینکریپت شده تا حد زیادی امن است.

        پاسخ
    2. حسن شفیعی ۱۱ اردیبهشت ۱۳۹۸

      سلام. مقدار متغییرهای $secret_key و $secret_iv را میتونید تغییر بدید.
      و بعد کافیه که به تابع نوع عملیات و رشته را پاس بدید تا نتیجه برای شما برگشت داده بشه.
      موفق باشید.

      پاسخ
      1. محمد جواد ۱۳ اردیبهشت ۱۳۹۸

        واقعا ممنونم . من هر چی به وبتون سر میزنم چه از مطالب و چه به صورت پاسخ های کامنتتون بیشتر یاد میگیرم .
        فقط یه سوال دیگه . الان این نوع رمز نگاری حداکثر طول رشته ای که تولید میکنه چه مقدار هست ؟

        پاسخ
      2. حسن شفیعی ۱۴ اردیبهشت ۱۳۹۸

        خیلی خوشحالیم که مطالب منتشر شده مفید واقع شده.
        چون از الگوریتم aes استفاده میشه می توان گفت که اندازه بلاک ۱۲۸بیت و کلید هم ۱۲۸،۱۹۲،۲۵۶ میتونه باشه.
        به هر حال مهم طول کاراکتر خروجی نیست و بدلیل داتشن کلید یا همان سالت به حدی امن است که به سادگی قابل کرک نیست. و بهتره برای ذخیره یا ارسال ان یکبار هم در آخر از base64 برای اینکد استفاده کنید تا کاراکترها به درستی منتقل ک خوانده بشوند.
        موفق باشید.

        پاسخ
  10. ایمان ۵ دی ۱۳۹۷

    بابت پاسخ گویی سریع سپاسگذارم 🙂
    یک سوال ، بعضی جاها دیدم که میگن نیاز به $iv نیست ، و بعضی از برنامه نویس ها اون رو خالی گذاشتن ، ایا خالی گذاشتن این مورد مشکلی به وجود خواهد آورد؟
    پیشاپیش بابت پاسخ تون سپاسگذارم.

    پاسخ
    1. حسن شفیعی ۵ دی ۱۳۹۷

      الگوریتم AES نیاز به ۱۶بایت برای پر کردن بلاک ها نیاز داره برای همین از تابع فوق برای محاسبه و ساختن یک رشته رندوم ۱۶ کاراکتری برای این رمزنگاری استفاده کردیم.
      لطفا داکیومنت خود php رو هم مطالعه و همچنین نتایج رو تست کنید. از iv برای دیکریپت کردن رمز استفاده کردیم و بله میتونید خالی بزارید
      http://www.php.net/manual/en/function.openssl-encrypt.php
      موفق باشید.

      پاسخ
  11. ایمان ۵ دی ۱۳۹۷

    سلام آقای شفیعی
    بابت زحمات ای که میکشید سپاسگذاریم.
    یک سوال داشتم ، من برنامه ام از رمزنگاری aes 256 cbc برای رمزنگاری استفاده کردم (بین کلاینت و سرور) و حالا نمیدونم چطور از این روش در php استفاده کنم ، ممنون میشم پاسخ بدید.
    من از ابزار : https://www.devglan.com/online-tools/aes-encryption-decryption
    برای تست استفاده میکنم ، لطفا یک مثال از روش رمزنگاری AES 256 CBC ذکر کنید ، با تشکر.

    پاسخ
    1. حسن شفیعی ۵ دی ۱۳۹۷

      سلام. خوشحالم که مطالب ارایه شده مفید واقع میشه.

      با تابع openssl رمزنگاری رشته ها به الگوریتم های مختلف به سادگی هرچه تمام تر قابل انجام است .
      یک مثال بسیار ساده مطابق با همین درخواست شما رو قرار می دم که به راحتی می توانید به عنوان یک تابع جمع کنید و در پروژه های مختلف استفاده کنید

      در ابتدا الگوریتم رمزنگاری خود رو بصورت یک ثابت در نظر گرفتیم که در مراحل بعدی بدون qoute کردن رشته از اون استفاده کنید.
      مرحله بعدی از openssl_random_pseudo_bytes برای ساخت یک کلید رمزنگاری ۲۵۶ بیت استفاده کردیم (در یک متغییر برای استفاده بعدی بصورت موقت ذخیره می کنیم.)

      بعد یک بردار اولیه برای رشته ایجاد می کنیم که آن هم برای شکستن رمز(decrypt) در آینده نیاز پیاده خواهیم کرد

      بعد با تابع openssl_encrypt() رشته مورد نظر را با الگوریتم aes 256 cbc کد می کنیم.

      توجه کنید چهار مقداری که دادیم عبارتند از $data : متغییر حاوی رشته ای که قصد کد کردن آن را داریم , الگوریتم رمزنگاری , کلید رمز , ۰ هم که به معنی آپشن های پیشفرض است که می توانید OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING هم قرار بدید و در نهایت کلید شکستن رمز.

      و به اینصورت خروجی ما بصورت کد شده با الگوریتم aes 256 cbc چاپ میشه که البته ما به جای ذخیره سازی کلید بازگردانی آن را با : به این رشته متصل کردیم (برای موارد حساس این مورد توصیه نمیشه و فقط جهت نمونه تست بود وگرنه شما باید این کلید رو جایی ذخیره کنید اگر قصد بازگردانه رشته اصلی را دارید)

      اگر احیانا کدهای شما اجرا نشد و با خطای call undefined function .. مواجه شدید توجه کنید که باید اکستنشن موردنظر روی سرور فعال باشه (بررسی از طریق تابع phpinfo() و فعال سازی از فایل php.ini )
      ;extension=php_openssl.dll
      همچنین ورژن php باید بالا باشه.

      موفق باشید.

      پاسخ
  12. محمد جواد ۵ آذر ۱۳۹۷

    ممنون از پاسخگویی . پس اگر مقدور بود یا در انتهای همین پست یا پست جدید در رابطه با openssl_encrypt هم آموزشی قرار بدین

    پاسخ
    1. حسن شفیعی ۵ آذر ۱۳۹۷

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

      پاسخ
  13. محمد جواد ۵ آذر ۱۳۹۷

    سلام . میشه در رابطه با تابع mcrypt_encrypt توضیحات بیشتری بدین . یک مثلا عملی هم لطفا بزنید .
    در قسمت کدی که برای mcrypt_encrypt قرار دادین یه سری از موارد رو کامنت کردین که مشخص نیست چی هستش.
    همچنین در قسمت کد نمونه از تابع base64_encode استفاده کردین که دلیلش رو نفهمیدم .
    ممنون میشم توضیح بدین

    پاسخ
    1. حسن شفیعی ۵ آذر ۱۳۹۷

      سلام. تابع mcrypt_encrypt منقضی شده و دیگر در ورژن های جدید php استفاده نمیشه و به جاش میتونید از openssl_encrypt بهره ببرید.
      base64_encode هم یک تابع با قابلیت برگشتی به حالت قبل و بسیار ساده است و معمولا برای اینکه رشته های عجیب و غریب رو نبینیم از تابع بهره می بریم.
      موفق باشید.

      پاسخ
  14. علی یعقوبی ۱ مرداد ۱۳۹۷

    سلام من میخواستم که کاربر بعد از اینکه صفحه وب رو سیو کرد با استفاده از Ctrl + S یک محتویات بهش اضافه بهش مثلا صفحه دیگه کار نکنه و رفرش خودکار بشه!

    ممنون میشم جواب رو به ایمیلم ارسال کنید

    با تشکر

    پاسخ
    1. حسن شفیعی ۱ مرداد ۱۳۹۷

      سلام . کد کامل در اختیار شما قرار نمیگیره و فقط نکته رو به شما میگیم و خودتون باید جستجو و درنهایت پیاده سازی کنید.

      از keyCode ها در جاوااسکریپت استفاده کنید که در صورتی که کلید های ctrl یا s زده شده دستور document.body.innerHTML = “خطا خطا خطا”; را اجرا کنید تا کل محتویات صفحه پاک بشه.

      موفق باشید.

      پاسخ
  15. soroosh ۲۶ تیر ۱۳۹۷

    سلام ممنون از مقاله هاي خوبتون،شما اول مقاله گفتيد md5 يا hash امنيت كمتري دارن!پس چرا توصيه كردين از اينا استفاده كنيم؟!

    پاسخ
    1. حسن شفیعی ۲۶ تیر ۱۳۹۷

      سلام . خوشحالم که مفید واقع شده . بله و فقط برای جلوگیری از لو رفتن رمزعبورهای شما حتی با هک شدن دیتابیس به روش هایی مثل sql injection توصیه شده ,حتما از رمزنگاری ها استفاده کنید. که خب فرقی نداره میتونید از روش های دیگه هم استفاده کنید و فقط مقصود این بود که توصیه کنیم که به هیچ وجه رمزعبور ها رو بصورت متن ساده (plain text) استفاده کنید. حالا فرقی ندارد از چه الگوریتمی بهره می برید در هر حال امنیت این روش ها همیشه نسبت به متن ساده بیشتر است.

      موفق باشید.

      پاسخ
دوره های آموزشی