فرایند *چکیده سازی* یا `hashing` معمولا برای تبدیل یک حجم داده به رشته کوچکی از عبارات استفاده میشود.
داده `hash`شده قابل برگشت نمیباشد.
یعنی نمیتوان از روی یک مقدار `hash` داده اصلی را حدس زد.
ولی با در اختیار داشتن داده اصلی و رشته `hash`شده میتوان اصالت داده اصلی را تعیین کرد.
بدین ترتیب یکی از مزایای استفاده از `hash` را میتوان کسب اطمینان از اصالت دادههای منتقل شده و عدم دستکاری توسط اشخاص دیگر عنوان کرد.
ما برای تضمین اصالت پیامهای کاربران در یک سیستم چت، میخواهیم ساختاری را ایجاد نماییم که با استفاده از آن بتوان یک پیام را با الگوریتمهای مختلف براساس انتخاب کاربران چکیده سازی نماییم.
# معرفی
پروژه اولیه را میتوانید از [اینجا](https://quera.ir/qbox/download/ZvpGAkMDS8/hashing.zip) دانلود کنید.
برای شروع میخواهیم امکان چکیده سازی پیامها با دو استراتژی `sha1` و `md5` امکان پذیر باشد.
اما در آینده ممکن است بخواهیم استراتژیهای بیشتری را پشتیبانی کنیم.
هر استراتژی باید یک کلاس متناظر داشته باشد که الگوریتم چکیده سازی مختص خود را پیاده سازی کرده باشد.
ما برای پشتیبانی استراتژیهای فعلی، دو کلاس `SHA1Hash` و `MD5Hash` را ایجاد نمودهایم.
### فایل `HashFactory.php`
برای مدیریت استراتژیهای ممکن، نیاز به کلاسی داریم که استراتژیهای موجود را به همراه کلاسهای متناظرشان، مدیریت کند.
برنامه باید به گونهای پیاده سازی شود که اگر استراتژیهای موجود به بیش از چند ده مورد افزایش پیدا کرد، باز هم مدیریت استراتژیهای موجود، به سادگی قابل انجام باشد.
برای انجام این کار یک کلاس به نام `HashFactory` ایجاد کردهایم.
وظیفه این کلاس ایجاد کلاسهایی هست که چکیده سازی را با الگوریتمهای مشخص شده انجام میدهند.
این کلاس شامل دو متد میباشد.
1. `register`:
این متد، دو پارامتر میگیرد که اولی نام الگوریتم چکیده سازی (مثلا `sha1`) و دومی یک نمونه از کلاسی است که وظیفه چکیده سازی با این الگوریتم را برعهده دارد.
2. `make`:
این تابع نام یک الگوریتم چکیده سازی را ورودی میگیرد و در خروجی کلاسی را برمیگرداند که با استفاده از این الگوریتم چکیده سازی میکند.
در ابتدای برنامه، الگوریتمهای پشتیبانی شده توسط برنامه را به همراه یک نمونه از شی متناظر این استراتژی را در این کلاس ثبت میکنیم. ( با استفاده از متد `register`).
سپس در مرحله بعد، شیای که توانایی چکیده سازی با استراتژی انتخاب شده توسط کاربر را دارد، از این کلاس تحویل میگیریم. (متد `make`)
### فایل `HashStrategy.php`
اینترفیسی طراحی کردهایم که تمام کلاسهای چکیده سازی موظف هستند، آن را پیاده سازی نمایند.
این اینترفیس تنها شامل تابعی به نام `hash` میباشد.
این تابع یک رشته را به عنوان ورودی میگیرد و نتیجه چکیده سازی توسط الگوریتم متناظر را، خروجی میدهد.
### فایلهای `SHA1Hash.php` و `MD5Hash.php`
هرکدام از استراتژیهای چکیده سازی باید از طریق یک کلاس پیاده سازی شوند. این کلاسها اینترفیس `HashStrategy` را پیاده سازی میکنند.
پیاده سازی این کلاسها باید از الگوی *Singleton* پیروی نماید.
به این معنی که در طول اجرای برنامه تنها یک شی از این کلاس قابل نمونه سازی باشد.
این دو کلاس باید متد `hash` را به گونهای پیاده سازی کنند که توانایی چکیده سازی مقدار ورودی با استفاده از الگوریتم متناظرشان را داشته باشد.
با توجه به وجود کلاس `HashFactory` برای مدیریت استراتژیهای مختلف، این کلاسها را به گونهای محدود کنید، که در خارج از کلاس قابل نمونه سازی با استفاده از عبارت `new` نباشند.
تنها راه دسترسی به اشیا نمونه سازی شده از این کلاسها باید متد `getInstance` باشد.
همچنین باید متد `getInstance` را به گونهای پیاده سازی نمایید که در طول برنامه، پس از چندین بار فراخوانی، تنها یک شی از این کلاس بسازد و در فراخوانیهای بعدی همان شیای که قبلا ساخته شده برگردانده شود.
# پیاده سازی
### فایل `HashFactory.php`
متد `register` و `make` را به گونهای پیاده سازی نمایید که بعد از فراخوانی به شکل زیر، بتواند یک نمونه از شیای که قابلیت `hash` کردن داده با الگوریتم مناسب را دارد، برگرداند.
```php
$factory = new HashFactory();
$factory->register('sha1', SHA1Hash::getInstance());
$factory->register('md5', MD5Hash::getInstance());
$hasher = $factory->make($_GET['strategy']);
```
### فایلهای `SHA1Hash.php` و `MD5Hash.php`
1. تابع سازنده کلاس را به گونهای تغییر دهید که امکان نمونه سازی از کلاس، در خارج از آن، امکان پذیر نباشد.
2. متد `getInstance` را به گونهای پیاده سازی کنید که با هربار فراخوانی تنها یک نمونه از کلاس ساخته شده را، یک شی نمونه سازی شده واحد را برگرداند.
3. تابع `hash` را برای هر استراتژی به گونهای پیاده سازی کنید، که با الگوریتم متناسب همان استراتژی، عملیات چکیده سازی را انجام دهد.
کلاسها باید به گونهای پیاده سازی شوند، که با هر بار اجرای فایل `index.php` رشته موجود در متغیر `$_GET['data']` با استفاده از استراتژی موجود در متغیر `$_GET['strategy']`، چکیده سازی شده و رشته حاصل در صفحه چاپ شود.
همچنین در صورتی که استراتژی موجود، در برنامه پشتیبانی نشود، باید یک `Exception` با پیام `Strategy Not Supported` پرتاب شود و اجرای برنامه خاتمه یابد. مثلا اگر کاربر درخواستی با مقدار `$_GET['strategy'] = 'sha256'` ارسال کند، برنامه باید این `Exception` را پرتاب کند.
توجه کنید در هر فایل نباید بیش از یک کلاس تعریف شود.
شما باید در کلاسهای مختلف، تنها بخشهایی که کامنت `Implement` را دارند، توسعه دهید.
همچنین، توجه کنید که فایل ها به صورت خودکار `require` میشوند. شما در هیچ کدام از فایل ها نیازی به `require` یا `include` ندارید.
در نهایت فایلهای زیر را در یک فایل *ZIP* قرار داده و آپلود نمایید. نام فایل *ZIP* اهمیتی ندارد.
1. `HashFactory.php`
2. `MD5Hash.php`
3. `SHA1Hash.php`
توجه کنید که فقط حق تغییر سه فایل بالا را دارید و نمیتوانید محتوای دیگر فایلها را تغییر دهید.