توابع هش (Hash Function) در دنیای کامپیوتر استفادههای متفاوت و زیادی دارند.
در این نوشته میخواهیم با این دسته از توابع آشنا شویم.
تابع هش یا Hash Function
به هر تابعی که مقادیر ورودی (کلیدها/Keys) با اندازه دلخواه را قبول کند و آن را به یک خروجی با اندازه ثابت (مقدارها/Values) نگاشت کند، تابع هش گویند.
برای مثال یک هش فانکشن بسیار ساده به شکل زیر است:
این تابع هش، نام و نام خانوادگی از هر اندازهای میگیرد و در عوض یک عدد ثابت (1 یا 2) برمیگرداند.
توجه کنید که ورودی میتواند اندازه متفاوت داشته باشد، در حالیکه خروجی همیشه یا 1 است یا 2.
به این تابع یک تابع هش (Hash Function) و به خروجیهای آن (در اینجا 1 و 2) مقادیر هش (Hash Value) میگویند.
به عمل استفاده از توابع هش برای ایندکس کردن یک جدولهش، هشینگ (Hashing) میگویند.
کاربرد توابع هش
این نوع از توابع در ذخیره کردن دادهها و البته فراخوانی دادههای ذخیرهشده کاربرد دارند. دلیل استفاده از این نوع توابع در ذخیرهسازی دادهها، سرعت بالای فراخوانی دادهها میباشد. یکی از دلایل آن این است که جستجوی یک Value کوتاه راحتتر از جستجو کردن یک عبارت بلند است. پس بجای پیدا کردن "سید پویا طباطبایی" به دنبال 01 میگردیم.
اما شاید بپرسید، 01 که تنها برای "سید پویا طباطبایی" نیست! که در اینجا مفهوم تصادم بوجود میآید.
تصادم یا Collision
تابعی که در بالا کشیده شده است، اصطلاحا تصادم (Collision) دارد. به این معنا که ورودیهای متفاوتی وجود دارند که اگر آنها را به تابع بدهیم، خروجی آنها یکسان خواهند بود.
برای مثال به ازای ورودیهای: "احسان احسانی" و "سید پویا طباطبایی" تابع خروجی یکسان (عدد 1) داده است.
کم بودن تصادم، یکی از معیارهای کیفی توابع هش میباشد، یعنی هر چه تصادم کمتر باشد، تابع هش بهتری داریم.
توابع هش رمزنگاری (Cryptographic Hash Functions)
این دسته از توابع هش، اصطلاحا یک طرفه (One-Way) هستند. به این معنا که معکوس کردن آنها عملا غیرممکن است.
با یک مثال ساده، سعی میکنیم مفهوم تابع یک طرفه را بهتر درک کنید.
فرض کنید یک تابع داریم که به عنوان ورودی 2 عدد اول بزرگ دریافت میکند و حاصل ضرب آنها را به عنوان خروجی میدهد. یعنی مثلا 572387 و 2910487 را دریافت میکند و 1,665,924,922,469 را تحویل میدهد. ضرب دو عدد برای کامپیوتر عملیات بسیار سادهای است و در کسری از ثانیه انجام میشود.
اما اگر بخواهیم معکوس این تابع حرکت کنیم، یعنی دو عددی را پیدا کنیم که اگر آنها را ضرب کنیم حاصل 1,665,924,922,469 بشود، کار بسیار زمانبر و سختی پیش رو داریم.
پس یک تابع داریم که خودش عملیات سادهای انجام میدهد، اما اگر بخواهیم عکس آن حرکت کنیم، به زمان بسیاری زیادی نیاز داریم.
میتوان گفت که امروزه دیگر هیچ پایگاهدادهای وجود ندارد که رمزعبور کاربران بصورت Plain Text درون آن ذخیره شده باشد. عموما رمزعبور کاربران را بوسیله یک Hash Function یک طرفه به یک Hash تبدیل میکنند و سپس آن Hash را درون پایگاه داده ذخیره میکنند.
دلیل اینکار نیز مشخص است. به این دلیل رمزعبور به صورت یک هش (Hash) ذخیره میشود که اگر یک مهاجم یا هکر به پایگاهداده پسوردها دسترسی پیدا کرد، پسوردها بصورت واضح برای او نمایش داده نشوند.
بنابراین حتی اگر هکر به پایگاه داده دسترسی پیدا کند، یک سری Hash بدست خواهد آورد که بدست آوردن رمزعبور کاربران از روی آن عملا غیرممکن است.