-
يكشنبه, ۶ تیر ۱۴۰۰، ۰۴:۲۴ ب.ظ
-
۷۰۰۸
هش (hash) و انواع آنها در پایتون
درود به همه !
در این پست به مبحث hashing در پایتون میپردازیم . همینطور که میدونید الگوریتم های hashing کاربرد گسترده ای در مباحث امنیتی دارند و هرروزه در دنیای هک و امنیت آموزش هایی مثل کرک هش MD5 یا ... را میبینیم . امروز میخوایم بررسی کنیم ببینیم اصلا هش چیه و چطوری میشه کرکش کرد . در ابتدا شروع میکنیم مباحث تعریفی راجع به هش ها رو میگیم و سپس میریم ببینیم چه کتابخونه ها و راه هایی برای کار با هش ها در پایتون وجود داره . با ما همراه باشید .
هش (hash) چیست ؟ هر هش ، یک الگوریتم ریاضیاتی است که در ازای دریافت یک داده با طول دلخواه به عنوان ورودی ، داده ای با طول ثابت و منحصر به فرد در خروجی تولید میکند .
طبق تعریف بالا ما میتوانیم داده ای با طول دلخواه به یک ورودی تابع هش بدهیم ولی در هر حالت خروجی با طول ثابت برای ما تولید خواهد کرد .
همینطور که در تصویر بالا مشاهده میکنید با سه ورودی متفاوت به یک تابع hash ، سه خروجی (digest) متفاوت نیز تولید شده است . دقت کنید در الگوریتم های hashing (بخصوص هش های رمزنگاری) معمولا یک تغییر کوچک در ورودی ، باعث تغییر بزرگی در مقدار خروجی میشود . برای مثال در تصویر بالا مثال دوم و سوم رو ببینید . تنها یک کلمه تغییر کرده ولی خروجی آن ها به طور کامل متفاوت از یکدیگر است . یک کلمه که هیچ ، حتی اگه یک کاراکتر هم تغییر کنه خروجی اصلا یه چیز دیگه میشه !! :)
نکته : در عمل و با توجه به قدرت پردازشی تکنولوژی های امروزی ، نمیتوان متن هش شده را به متن اصلی تبدیل کرد .
طبق نکته بالا شما با استفاده از الگوریتم های hashing فقط میتوانید یک متن را هش کنید ولی به هیچ عنوان نمیتوانید متن هش شده را به حالت اولیه برگردانید .
ممکن است این سوال پیش بیاید که هش ها به چه دردی میخورند ؟ وقتی فقط میشه یک متن رو هش کرد و نمیشه دیگه از متن هش شده به متن اصلی رسید پس به چه دردی میخوره ؟ کاربرد های بسیار زیادی داره در دنیای امنیت که میتونید در اینترنت بخونید راجع بهشون ولی یک مثال آن جلوگیری از جعل اطلاعات است . فرض کنید دوست شما قرار است یک سند برای شما ارسال کند . قبل از اینکه سند را ارسال کند ، هش آن را حساب میکند و به شما میگوید مثلا هش سند فلان عبارت است . پس از آن سند را برای شما ارسال میکند . شما هش سندی که به دستتان رسیده را حساب میکنید و با هشی که دوستتان قبلا به شما گفته بود مقایسه میکنید . اگر هش ها یکی بود یعنی سند به درستی و کامل به دست شما رسیده و دچار تغییرات نشده ولی اگر هش ها یکی نشد یعنی سند دستکاری شده یا ناقص به دست شما رسیده .
چند مورد از معروف ترین الگوریتم های hash :
MD5 : الگوریتم MD5 مخفف Message Digest version 5 یکی از معروف ترین الگوریتم های هش است . هش خروجی این الگوریتم 128 بیت طول دارد . مثال : هش عبارت mrpython با استفاده از الگوریتم MD5 ، برابر عبارت 9694e5fcf6b9c3a06a0191dac2193bc3 است . همینطور که میبینید تعداد حروف خروجی ، 32 کاراکتر است . از آنجایی که خروجی در مبنای 16 (HEX) است ، بنابراین هر رقم معادل 4 بیت است . بنابراین 4 * 32 برابر است با طول خروجی که 128 بیت میباشد .
SHA-1 : الگوریتم SHA-1 مخفف Secure Hash Algorithm version 1 یکی دیگر از معروف ترین الگوریتم های هش است . خروجی هش این الگوریتم 160 بیت طول دارد . مثال : هش عبارت mrpython با استفاده از الگوریتم SHA-1 برابر عبارت b6a6eae1ec24285de46c26558a90b69b44df8358 است .
SHA-2 : الگوریتم SHA-2 مخفف Secure Hash Algorithm version 2 نیز الگوریتم معروف و پر استفاده ای در بین الگوریتم های هش است . این ورژن از الگوریتم SHA ، خود شامل الگوریتم های SHA224 , SHA256 , SHA384 , SHA512 است . هر کدام از این الگوریتم ها خروجی با طول متفاوت دارند . طول خروجی هر الگوریتم رو به روی آن با عدد نوشته شده است. برای مثال SHA224 خروجی 224 بیت دارد ، SHA256 خروجی 256 بیت دارد ، SHA384 خروجی 384 بیت دارد و SHA512 خروجی 512 بیت دارد .
در پایتون کتابخانه ای به نام hashlib برای کار با هش ها وجود دارد .
مثال 1 : تولید هش MD5 در پایتون :
# Example 1 -> MD5 Generator
from hashlib import md5 text = input( "Text : " ) hash_of_text = md5( text.encode() ) print(hash_of_text.hexdigest())
در مثال بالا در ابتدا از کتابخانه ی hashlib ، تابع md5 که کار آن تولید هش md5 است را ایمپورت کردیم . سپس یک متن به عنوان ورودی تابع هش md5 از کاربر گرفته ایم .
متن داده شده را به شکل encode شده به ورودی تابع md5 داده ایم تا هش آن را برای ما حساب کند . خروجی تابع را در متغییر hash_of_text ذخیره کرده ایم .
سپس تابع hash_of_text.hexdigest را فراخوانی کردیم و خروجی آن را چاپ کردیم . خروجی این تابع ، خروجی هش MD5 در مبنای 16 (hex) است .
مثال 2 : تولید هش SHA-1 در پایتون :
# Example 2 -> SHA-1 Generator
from hashlib import sha1 text = input( "Text : " ) hash_of_text = sha1( text.encode() ) print(hash_of_text.hexdigest())
این سورس نیز دقیقا مانند سورس قبل است فقط به جای تابع md5 ، از تابع sha1 برای تولید هش SHA-1 استفاده کردیم .
مثال 3 : تولید هش sha256 در پایتون :
# Example 3 -> SHA256 Generator
from hashlib import sha256 text = input( "Text : " ) hash_of_text = sha256( text.encode() ) print(hash_of_text.hexdigest())
به همین روال میتوانید از انواع توابع مثل sha256 , sha512 , md5 , sha384 , .... موجود در کتابخانه ی hashlib استفاده کنید .
از آنجایی که نمیتوان از متن هش شده به متن اصلی رسید ، هکر ها برای پیدا کردن متن اصلی یک هش از حمله ی Brute Force استفاده میکنند . فرض کنید یک هکر ، هش پسووردی را در اختیار دارد و میخواهد متن اصلی هش که همان پسوورد است را بدست بیاورد . طی این حمله برای کرک هش ، هکر یک دیکشنری یا پسوورد لیست تهیه میکند ، سپس تمام پسوورد های داخل پسوورد لیست را با همان الگوریتمی که هش مورد نظر درست شده هش میکند و با هش مورد نظر مقایسه میکند . هش هرکدام از عبارت های پسوورد لیست با هش مورد نظر یکی شد یعنی پسوورد همان بوده است .
مثال : میخواهیم اسکریپتی بنویسیم که با استفاده از یک پسوورد لیست ، هش b6a6eae1ec24285de46c26558a90b69b44df8358 که هش یک پسوورد است را کرک کند . این هش با استفاده از الگوریتم SHA-1 بدست آمده است .
دقت کنید اگر با هشی مواجه شدیم که نمیدونستیم باچه الگوریتمی درست شده ، میتونیم یه نگاه به طول آن بیندازیم یا حتی با استفاده از کاراکتر هایی که در آن استفاده شده تشخیص دهیم . همچنین میشه از ابزار های آماده اینکار استفاده کنیم تا وقتمون گرفته نشه . برای مثال سایت زیر به طول آنلاین یک هش از شما میگیرد و الگوریتم آن را حدس میزند :
https://www.tunnelsup.com/hash-analyzer/
اسکریپت :
# HASH Cracker
from hashlib import sha1
hash = input("HASH : ")
passlist = open("passlist.txt")
for password in passlist : password = password.strip("\n") print("testing : {}".format(password)) hash_of_password = sha1(password.encode()).hexdigest() if hash_of_password == hash: print("*"*20) print("Password : {}".format(password)) break
در ابتدا از کتابخانه ی hashlib تابع sha1 را ایمپورت کرده ایم . از این تابع استفاده میکنیم چون میدانیم هش مورد نظر با این الگوریتم به دست آمده است . سپس یک ورودی به نام hash از کاربر میگیریم که همان هشی است که قرار است کرک کنیم .
پسوورد لیست مورد نظر را با استفاده از تابع open باز کرده ایم و در متغییر passlist ریختیم .
یک حلقه ی for روی پسوورد لیست اجرا کرده ایم تا به تمام پسوورد های پسووردلیست دسترسی پیدا کنیم . به ازای هر کدام از پسوورد های پسوورد لیست ، ابتدا n\ آخر آنها را حذف کرده ایم. سپس برای کاربر چاپ کردیم چه پسووردی رو داریم تست میکنیم . بعد از اون هش پسوورد را بدست آوردیم و ریختیم داخل متغییر hash_of_password . حالا این هش رو با هشی که کاربر وارد کرده مقایسه کردیم و گفتیم اگه برابر بود بیا پسوورد رو چاپ کن (وقتی برابر شدن یعنی پسوورد همین بوده ) .
پس از اجرای اسکریپت و دادن ورودی های لازم :
امیدوارم مفید بوده باشه . سوالی بود مطرح کنید .
یا حق !
Telegram Channel : @mrpythonblog