به نام خدا؛
سلام دوستان امیدوارم حالتون خوب باشه...
حتماً تا حالا براتون پیش اومده که بخواین یک فایلی که داخل سرور یا هاستتون وجود داره رو رمزنگاری کنین تا محتوای فایل غیر قابل مشاهده باشه.
امروز قصد داریم راجع به رمزنگاری فایلهای آپلود شده توی سرور یا هاستمون صرف نظر از فرمتشون صحبت کنیم. برای رمزنگاری رشته ها در PHP توابع زیادی به صورت پیشفرض در PHP تعریف شده اما برای رمزنگاری فایلها در PHP تابعی که به صورت پیشفرض در این زبان تعریف شده باشه متأسفانه موجود نیست. در ورژن های قبل از 7.2 این زبان با استفاده از افزونه (extension) mcrypt این امکان وجود داشت که با استفاده از این افزونه فایلها رو رمزنگاری کرد. اما متأسفانه این امکان در ورژن هفتم PHP وجود نداره. پس باید به دنبال راه جایگزین بود. امروز قصد داریم که فایلها رو با استفاده از الگوریتم AES-128-CBC رمزنگاری و رمزگشایی کنیم.
اجازه بدین اول با تابع رمزنگاری فایل شروع کنیم.
رمزنگاری فایل:برای اینکه بتونین یک فایلی که در دایرکتوری که این فایل PHP قرار داره رو رمزنگاری کنین باید ریکوئستی مشابه نمونه زیر ارسال کنین:شما باید به جای عبارت x برای پارامتر file نام فایل موردنظرتون رو به همراه فرمتش درج کنین.
همونطور که در کد بالا می بینید یک کلید خصوصی هم تعریف کردیم که برای رمزگشایی فایل به کارمون میاد. هر چی این کلید خصوصی طولانی تر باشه و کاراکترهای مختلفی داخلش استفاده شده باشه بهتره چرا که باعث میشه کرکر (Cracker) یا هکر نتونه با حملاتی مثل وردلیست یا بروت فورس نتیجه شاخصی بگیره.
بعد از اجرای کد بالا فایل موردنظر شما با فرمت .enc همونطور که در کد تعریف کردیم (میتونین این فرمت رو به دلخواه خودتون تغییر بدین) ذخیره میشه. یعنی اگر برای مثال نام فایل شما image.jpg باشه فایل رمزنگاری شده ای که این کد به شما تحویل میده image.jpg.enc خواهد بود. در ضمن فایل اصلی که رمزنگاری کردین بعد از انجام پروسه رمزنگاری حذف میشه چرا که هدف ما این هست که محتوای فایل قابل مشاهده نباشه.
رمزگشایی فایل:
برای رمزگشایی فایل رمزنگاری شده ای که در دایرکتوری این فایل PHP قرار داره از این کد استفاده میکنیم:برای رمزگشایی فایل موردنظرتون باید ریکوئستی مشابه نمونه زیر ارسال کنین:به جای عبارت y برای پارامتر file شما باید نام فایل رمزنگاری شده خودتون رو با احتساب فرمت و پسوند رمزنگاری که انتخاب کردین (توی بخش رمزنگاری صحبت کردم راجع بهش؛ من برای مثال اینجا .enc رو انتخاب کردم) وارد کنین تا فایل موردنظر رمزگشایی بشه.
فایل رمزگشایی شده با پسوند .dec ذخیره میشه که شما میتونین دقیقاً مثل پسوند رمزنگاری این پسوند رو هم به سلیقه خودتون شخصی سازی کنین. یعنی اگر شما فایل رمزنگاری شده image.jpg.enc رو با استفاده از این کد رمزگشایی کردین فایل رمزگشایی شده نامش میشه image.jpg.dec. پس شما میتونین روی فایل رمزگشایی شده پردازش داشته باشین.
در ضمن کلید خصوصی که در بخش رمزنگاری تعیین کردین رو باید حتماً برای رمزگشایی به خاطر داشته باشین.
نکته کاربردی برای بهینه سازی حجم کدها:
کدهایی که بنده قرار دادم تقریباً طولانی هستند. برای اینکه کدها رو کوتاه تر کنیم میتونیم از تکنیک include یا require در زبان PHP استفاده کنیم.
در واقع به نوعی ما فانکشن (تابع) رمزنگاری یا رمزگشایی رو به تنهایی در یک فایل مجزا مثلاً با نام function.php قرار میدیم و بعد اون رو توی یک فایل دیگه فراخوانی میکنیم.
دقت کنین که برای فراخوانی یک فایل PHP دیگه در فایل PHP دیگه راه های زیادی هست که بسته به شرایط به کار میاد. ولی به طورکلی همونطور که گفتم دو تابع require و include باید استفاده بشن. البته بماند که require_once و include_once رو هم داریم که یعنی یک بار فایل به روش require یا include فقط در همون قسمتی از برنامه که تعیین کردیم و نه کل برنامه مون فراخوانی بشه. اما تفاوت include با require در چی هست؟
وقتی ما از include استفاده میکنیم اگر اون فایل PHP که مشخص می کنیم که فراخوانی بشه مشکلی داشته باشه ادامه برنامه ما اجرا میشه ولی اگر از require استفاده کنیم و مشکلی در فایل PHP فراخوانی شده باشه ادامه برنامه اجرا نمیشه و برنامه از قسمت فراخوانی فایل متوقف میشه و به پایان میرسه.
با این توضیحات میفهمیم که در حالتی که الان باهاش مواجه هستیم باید فایل function.php رو از طریق تابع require فراخوانی کنیم.
دستور فراخوانی با تابع require یا include در کد PHP ما به این شکل میشه:اسم دیگه این تکنیک اصطلاحاً ساختن مستر پیج و صفحات فرعی هست. همونطور که گفته شد استفاده از این تکنیک میتونه کدهای شما رو کوتاه تر بکنه و البته اگر مشکلی هم پیش بیاد پیدا کردن مشکل خیلی ساده تر خواهد بود.
پ.ن: دقت کنین که همونطور که در ابتدای تاپیک گفتم شما میتونین هر فایلی توی هاستتون رو با هر فرمتی رمزنگاری و رمزگشایی کنین. میخواد فایل شما یک تصویر باشه یا یک فایل txt یا فایل json و یا هر فایلی. در ضمن چیزی که باعث میشه امنیت این روش بیشتر بشه استفاده از کلید خصوصی ایمن و دارای طول مناسب و تصادفی هست. چرا که تصادفی بودن باعث میشه مهاجم نتونه با روش های حمله جامع آماری و یا لیست های از پیش آماده شده کار زیادی پیش ببره. پس حتماً به این موضوع دقت داشته باشین.
استفاده از این روش و اعمال یکسری تنظیمات در فایل .htaccess میتونه امنیت سمت سرور شما رو تا حد بسیار بالایی تأمین کنه و دیگه نگرانی بابت مقوله امنیت نداشته باشین. البته بماند که امنیت هیچ وقت صد درصد نیست!
امیدوارم که از این مطلب کاربردی لذت برده باشین.
خوشحال میشم نظراتتون رو بیان کنین.
با آرزوی بهترین ها...
سلام دوستان امیدوارم حالتون خوب باشه...
حتماً تا حالا براتون پیش اومده که بخواین یک فایلی که داخل سرور یا هاستتون وجود داره رو رمزنگاری کنین تا محتوای فایل غیر قابل مشاهده باشه.
امروز قصد داریم راجع به رمزنگاری فایلهای آپلود شده توی سرور یا هاستمون صرف نظر از فرمتشون صحبت کنیم. برای رمزنگاری رشته ها در PHP توابع زیادی به صورت پیشفرض در PHP تعریف شده اما برای رمزنگاری فایلها در PHP تابعی که به صورت پیشفرض در این زبان تعریف شده باشه متأسفانه موجود نیست. در ورژن های قبل از 7.2 این زبان با استفاده از افزونه (extension) mcrypt این امکان وجود داشت که با استفاده از این افزونه فایلها رو رمزنگاری کرد. اما متأسفانه این امکان در ورژن هفتم PHP وجود نداره. پس باید به دنبال راه جایگزین بود. امروز قصد داریم که فایلها رو با استفاده از الگوریتم AES-128-CBC رمزنگاری و رمزگشایی کنیم.
اجازه بدین اول با تابع رمزنگاری فایل شروع کنیم.
رمزنگاری فایل:
کد php:
<?php
/**
* @author Master Badfar
* @copyright 2020
*/
// تابع رمزنگاری به کمک الگوریتم AES-128-CBC
define('FILE_ENCRYPTION_BLOCKS', 10000);
function encryptFile($source, $key, $dest)
{
$key = substr(sha1($key, true), 0, 16);
$iv = openssl_random_pseudo_bytes(16);
$error = false;
if ($fpOut = fopen($dest, 'w')) {
fwrite($fpOut, $iv);
if ($fpIn = fopen($source, 'rb')) {
while (!feof($fpIn)) {
$plaintext = fread($fpIn, 16 * FILE_ENCRYPTION_BLOCKS);
$ciphertext = openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
$iv = substr($ciphertext, 0, 16);
fwrite($fpOut, $ciphertext);
}
fclose($fpIn);
} else {
$error = true;
}
fclose($fpOut);
} else {
$error = true;
}
return $error ? false : $dest;
}
// پایان تابع
//
// دریافت نام فایل موردنظر برای رمزنگاری و ذخیره آن در یک متغیر
$fileName = $_GET['file'];
// تعریف کلید خصوصی جهت رمزگشایی
$key = 'X@7O^5zFv7y2svB';
// استفاده از تابع تعریف شده برای رمزنگاری
encryptFile($fileName, $key, $fileName . '.enc');
// حذف فایل اصلی
unlink($fileName);
// نمایش پیغام موفقیت آمیز بودن
echo "Done!";
?>
کد:
http://yourhost.com/file.php?file=x
همونطور که در کد بالا می بینید یک کلید خصوصی هم تعریف کردیم که برای رمزگشایی فایل به کارمون میاد. هر چی این کلید خصوصی طولانی تر باشه و کاراکترهای مختلفی داخلش استفاده شده باشه بهتره چرا که باعث میشه کرکر (Cracker) یا هکر نتونه با حملاتی مثل وردلیست یا بروت فورس نتیجه شاخصی بگیره.
بعد از اجرای کد بالا فایل موردنظر شما با فرمت .enc همونطور که در کد تعریف کردیم (میتونین این فرمت رو به دلخواه خودتون تغییر بدین) ذخیره میشه. یعنی اگر برای مثال نام فایل شما image.jpg باشه فایل رمزنگاری شده ای که این کد به شما تحویل میده image.jpg.enc خواهد بود. در ضمن فایل اصلی که رمزنگاری کردین بعد از انجام پروسه رمزنگاری حذف میشه چرا که هدف ما این هست که محتوای فایل قابل مشاهده نباشه.
رمزگشایی فایل:
برای رمزگشایی فایل رمزنگاری شده ای که در دایرکتوری این فایل PHP قرار داره از این کد استفاده میکنیم:
کد php:
<?php
/**
* @author Master Badfar
* @copyright 2020
*/
// تابع رمزگشایی الگوریتم AES-128-CBC
function decryptFile($source, $key, $dest)
{
$key = substr(sha1($key, true), 0, 16);
$error = false;
if ($fpOut = fopen($dest, 'w')) {
if ($fpIn = fopen($source, 'rb')) {
$iv = fread($fpIn, 16);
while (!feof($fpIn)) {
$ciphertext = fread($fpIn, 16 * (FILE_ENCRYPTION_BLOCKS + 1));
$plaintext = openssl_decrypt($ciphertext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
$iv = substr($ciphertext, 0, 16);
fwrite($fpOut, $plaintext);
}
fclose($fpIn);
} else {
$error = true;
}
fclose($fpOut);
} else {
$error = true;
}
return $error ? false : $dest;
}
// پایان تابع
//
// دریافت نام فایل موردنظر برای رمزنگاری و ذخیره آن در یک متغیر
$fileName = $_GET['file'];
// تعریف کلید خصوصی جهت رمزگشایی
$key = 'X@7O^5zFv7y2svB';
// استفاده از تابع تعریف شده برای رمزگشایی
decryptFile($fileName . '.enc', $key, $fileName . '.dec');
// نمایش پیغام موفقیت آمیز بودن
echo "Done!";
?>
کد:
http://yourhost.com/file.php?file=y
فایل رمزگشایی شده با پسوند .dec ذخیره میشه که شما میتونین دقیقاً مثل پسوند رمزنگاری این پسوند رو هم به سلیقه خودتون شخصی سازی کنین. یعنی اگر شما فایل رمزنگاری شده image.jpg.enc رو با استفاده از این کد رمزگشایی کردین فایل رمزگشایی شده نامش میشه image.jpg.dec. پس شما میتونین روی فایل رمزگشایی شده پردازش داشته باشین.
در ضمن کلید خصوصی که در بخش رمزنگاری تعیین کردین رو باید حتماً برای رمزگشایی به خاطر داشته باشین.
نکته کاربردی برای بهینه سازی حجم کدها:
کدهایی که بنده قرار دادم تقریباً طولانی هستند. برای اینکه کدها رو کوتاه تر کنیم میتونیم از تکنیک include یا require در زبان PHP استفاده کنیم.
در واقع به نوعی ما فانکشن (تابع) رمزنگاری یا رمزگشایی رو به تنهایی در یک فایل مجزا مثلاً با نام function.php قرار میدیم و بعد اون رو توی یک فایل دیگه فراخوانی میکنیم.
دقت کنین که برای فراخوانی یک فایل PHP دیگه در فایل PHP دیگه راه های زیادی هست که بسته به شرایط به کار میاد. ولی به طورکلی همونطور که گفتم دو تابع require و include باید استفاده بشن. البته بماند که require_once و include_once رو هم داریم که یعنی یک بار فایل به روش require یا include فقط در همون قسمتی از برنامه که تعیین کردیم و نه کل برنامه مون فراخوانی بشه. اما تفاوت include با require در چی هست؟
وقتی ما از include استفاده میکنیم اگر اون فایل PHP که مشخص می کنیم که فراخوانی بشه مشکلی داشته باشه ادامه برنامه ما اجرا میشه ولی اگر از require استفاده کنیم و مشکلی در فایل PHP فراخوانی شده باشه ادامه برنامه اجرا نمیشه و برنامه از قسمت فراخوانی فایل متوقف میشه و به پایان میرسه.
با این توضیحات میفهمیم که در حالتی که الان باهاش مواجه هستیم باید فایل function.php رو از طریق تابع require فراخوانی کنیم.
دستور فراخوانی با تابع require یا include در کد PHP ما به این شکل میشه:
کد php:
include/require ('file.php');
پ.ن: دقت کنین که همونطور که در ابتدای تاپیک گفتم شما میتونین هر فایلی توی هاستتون رو با هر فرمتی رمزنگاری و رمزگشایی کنین. میخواد فایل شما یک تصویر باشه یا یک فایل txt یا فایل json و یا هر فایلی. در ضمن چیزی که باعث میشه امنیت این روش بیشتر بشه استفاده از کلید خصوصی ایمن و دارای طول مناسب و تصادفی هست. چرا که تصادفی بودن باعث میشه مهاجم نتونه با روش های حمله جامع آماری و یا لیست های از پیش آماده شده کار زیادی پیش ببره. پس حتماً به این موضوع دقت داشته باشین.
استفاده از این روش و اعمال یکسری تنظیمات در فایل .htaccess میتونه امنیت سمت سرور شما رو تا حد بسیار بالایی تأمین کنه و دیگه نگرانی بابت مقوله امنیت نداشته باشین. البته بماند که امنیت هیچ وقت صد درصد نیست!
امیدوارم که از این مطلب کاربردی لذت برده باشین.
خوشحال میشم نظراتتون رو بیان کنین.
با آرزوی بهترین ها...