صد رازِ نهان

یک شمع، با روشن کردن شمعی دیگر چیزی از دست نمی‌دهد!

۳ مطلب با کلمه‌ی کلیدی «Hash» ثبت شده است

رمزنگاری/4-معیارهای امنیت

قسمت قبلی: مشکلات مربوط به Encoding

تا پیش از این با Hash کردن و Encoding و Decoding آشنا شدیم و دانستیم که Hashing استفاده از تابعی است که یک طرفه می‌باشد و پس از Hash کردن داده ها قابلیت بازیابی مجدد آن‌ها را نداریم، و در مقابل دانستیم که Encoding و Decoding تابع هایی دو طرفه برای تغییر Form داده ها هستند؛ که برای استفاده از آن‌ها نیاز به چیزی تحت عنوان کلید یا رمز نیست و هر فردی که از الگوریتم مطلع باشد می‌تواند داده های Encode شده را با استفاده از تابع Decode به داده های اصلی تبدیل کند.(لازم به ذکر است که ماهیت Public بودن قریب به اتفاق الگوریتم های Encoding/Decoding باعث می‌شود همه بتوانند از آن‌ها استفاده کنند).


معیارهای امنیت:

 در این قسمت ابتدا یک سناریو تعریف می‌کنیم و سپس بر اساس آن، علت نیاز به الگوریتم‌هایی فراتر از الگوریتم‌های Hash و Encoding/Decoding را متوجه خواهیم شد و در خلال قسمت های بعدی روند توسعه‌ی این الگوریتم‌های مورد نیاز را توضیح می‌دهیم.

در این سناریو شما فرمانده ی یک سپاه جنگی هستید و به سبب لزوم نظارت بر اتفاقات خط نبردِ نیروهایتان و نیز مدیریت کارهای مملکتی، ناچارید که مدام بین میدان کارزار و مقرّ فرماندهی آمد و شد کنید(بگذارید حداقل در این داستان سناریو را طوری تعریف کنیم که گویا نعلین فرماندهان نیز گَرد خطوط نبرد را به شیارهای خود دیده است!). بنابرین شما نیاز دارید که گاهی از این مقر، به یکی از سربازان عالی‌رتبه‌ی خود که وِی را به عنوان جانشین بر مسند فرماندهی گمارده‌اید نامه ای ارسال کنید و او را در جریان کارهایی که باید انجام دهد قرار دهید. همچنین، فرمانده ی مذکور، باید گزارشاتی از عملکرد خودش و اوضاع به شما ارسال کند. پیش از این که ادامه‌ی داستان را تعریف کنیم، یک نام برای شما، و یک نام برای آن افسر عالی‌رتبه انتخاب می‌کنیم. نام شما Bob است، و نام آن افسر Alice (چرا تعجب کردید؟ یک افسر عالی‌رتبه نمی‌تواند خانم باشد؟).


سوال: چرا Bob و چرا Alice؟ 

پاسخ: آلیس و باب در واقع دو عضو از یک خانواده‌ی بزرگ هستند تحت عنوان خانواده‌ی کاراکترهای رمزنگاری! به صورت واضح تر، در سال 1978 یکی از اساتید دانشگاه MIT به نام رونالد ریوست، در مقاله ای که برای ارائه‌ی الگوریتم رمزنگاری RSA آماده کرده بود، از این اسامی برای مثال‌های خود به عنوان فرستنده و گیرنده‌ی پیام استفاده کرد. بعدها در دیگر سناریوهایی که طراحی شد، این اسامی شهرت یافتند و کم کم کاراکترهای دیگری هم به جمع آن‌ها پیوستند. برای رعایت این رسم، ما نیز در سناریوی خود همین کاراکترها را به کار می‌بریم. به عنوان یک مطلب اضافه، حرف R در الگوریتم RSA، از فامیل آقای Rivest گرفته شده است. دو حرف دیگر هم از نام دو طرِاح دیگر الگوریتم آمده اند.

دکتر ریوست (نفر وسط)

خب، تصمیم باب بر این شده است که در یک نامه، دستورات خود را به آلیس عزیزش در میدان نبرد ابلاغ کند.

اما بیایید پیش از آنکه اتفاقات و راهکارهایی که "باب" و "آلیس" استفاده کردند را بیان کنیم، خودمان بررسی کنیم و ببینیم که چه مسائلی باید در نظر می‌گرفتند؟ [بعدها خواهیم دید این مسائل مبنای امنیت یک خط ارتباطی را تشکیل می‌دهند]:

  1. "باب" و "آلیس" باید به نحوی در نامه هایشان، خود را به گونه‌ای به یکدیگر معرفی کنند که هر کدام هنگام دریافت نامه‌ی دیگری بتواند مطمئن شود که نامه از جانب همان شخصی آمده است که باید بیاید. حتی در صورتی که نیروهای دشمن رونوشتی را که هفته‌ی پیش در کاروان‌سرای بین راه از نامه‌ی قاصد تهیه کردند جایگزین نامه‌ی امروز قاصد کنند، دریافت کننده باید متوجه معتبر نبودن آن بشود. [بعد ها این بند را با نام Authenticity خواهید شناخت]
  2. در صورتی که نیروهای دشمن در میانه‌ی مسیر قاصد را تطمیع کردند یا به قتل رساندند و به دستوراتِ "باب" یا گزارشِ "آلیس" دست یافتند، نباید از آن چیزی متوجه شوند! [بعد ها این بند را با نام Confidentiality خواهید شناخت]
  3. در صورتی که نیروهای دشمن در کاروان سراهای میان راه کمین کردند و نامه‌ اصلیِ قاصد را دزدیدند و محتوای آن را عوض کردند یا نامه‌ی جدیدی که خودشان نوشته اند جایگزین آن کردند، دریافت کننده‌ی نامه‌ی جدید باید متوجه جعلی بودن آن بشود. [بعد ها این بند را با نام Integrity خواهید شناخت]
  4. چنانچه "باب" دستوری به آلیس فرستاد و مثلا به وی فرمانِ "حمله" داد و آلیس بعد از خواندن دستور، به خاطر ترس یا ... به آن عمل نکرد، بعدها نباید بتواند ادعا کند که نامه را دریافت نکرده است! همینطور اگر "باب" در موقیعت مشابهی، مثلا در حالت مستی، تصمیم اشتباهی گرفت و فرمانی صادر کرد و به آلیس فرستاد و اجرای آن تصمیمِ اشتباه منجر به اتفاق بدی شد که آبروی "باب" را به خطر می‌انداخت، وی نباید قادر به این باشد که ارسال آن دستور را انکار کند. [بعد ها این بند را با نام Non-Repdiation خواهید شناخت]
  5. قاصد و اسب پر انرژی اش همیشه باید در دسترس "باب" و آلیس باشد. [بعد ها این بند را با نام Availability خواهید شناخت]
لازم به ذکر است که پیاده سازی کردن بعضی الزامات بالا ممکن است به پیاده سازی مورد دیگر نیز منجر شود. یعنی این که، موارد بالا ارتباط تنگاتنگی با یکدیگر دارند. در پست های بعدی با تفاوت آن‌ها آشنا خواهیم شد.


To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.
Ralph Waldo Emerson
۲۳ مهر ۹۴ ، ۰۰:۲۴ ۱ نظر موافقین ۰ مخالفین ۰
ابراهیم قاسمی

رمزنگاری-مقدمه/2-اِنکُدینگ و دیکُدینگ


خیلی خب! در قسمت قبل (یعنی این پست) با "Hash" کردن یا دَرهم نگاری آشنا شدیم و فهمیدیم که هَش کردن یعنی اختصاص یک رشته ی با طول ثابت به یک ورودی دلخواه، با این شروط که:

  1. از روی مقدار هش مقدار ورودی قابل تولید نباشد.
  2. احتمال این که به ازای دو ورودی مختلف، یک خروجی تولید شود به قدری کم باشد که قابل چشم پوشی باشد.
همچنین فهمیدیم که الگوریتم های Hash کردن، کلید یا رمز ندارند و همه چیز صرفا یک الگوریتم است که تنها ورودی آن داده ی مورد نیاز برای Hash شدن است. برای عملی تر شدن توضیحات، می توانید با مراجعه به این سایت یا این سایت عبارت های مورد نظر خود را با چند الگوریتم مشهور دَرهم نگاری هش کنید. به هر حال من قبلا این کار را برای عبارت "This is a sample plain text" انجام داده ام و نتیجه را برای شما داخل عکس زیر آماده کرده ام:

Hash

و اما:
قسمت 2: Encoding/Decoding

معرفی فرایند:
چیزی که در این پست با آن آشنا می‌شویم، Encoding و Decoding است. طبق نوشته‌ی ویکی‌پیدا، Encoding به فرایند جایگزینی کاراکترها و رشته با کاراکترها و رشته های دیگری است که انتقال یا ذخیره‌ی آنها برای یک سیستم بهینه تر باشد و همچنین، عمل Decoding تغییر دوباره ی فرمت این کاراکترهای Encode شده به فُرم اولیه‌ی آنها می‌باشد. 
اما اگر بخواهیم به زبان ساده تر بیان کنیم، Encode کردن و Decode کردن مشابه فرایند ترجمه ی یک متن از یک زبان به زبان دیگر است. یعنی همانطور که در دنیای واقعی می‌توان یک متن فارسی را به راحتی به زبان های مختلف دیگر ترجمه کرد و بعد دوباره به متن اصلی بازگرداند، در دنیای رایانه‌ها هم می‌توان یک داده را به فرمت های مختلف ترجمه یا در اصطلاح Encode کرد و بعد دوباره به فرمت اولیه بازگرداند یا اصطلاحا Decode کرد و باز همانطور که در دنیای واقعی اگر زبان مقصد معادلی برای قسمتی از متن اصلی نداشته باشد، ترجمه ی آن قسمت امکان پذیر نیست، در دنیای رایانه هم گاها، Encode کردن یک داده از یک فرمت به فرمت دیگر، به خاطر پشتیبانی نکردن فرمت مقصد از قسمتی از داده ی ورودی، با شکست مواجه می‌شود. (یا به داده هایی غیر قابل بازگشت تبدیل می شوند.)
بنابراین، با توجه به مثال ارائه شده، Encode و Decode کردن تغییر فرمت(نحوه‌ی نمایش) یک متن/داده است به گونه ای که:
  1.  قابل بازگشت باشد.
  2. هر شخصی بدون نیاز به هیچگونه کلید یا رمزی و تنها با اطلاع از ساختار آن فرمت ها، قادر به انجام آن باشد.
از آنجا که با ارائه شدن هر محصول یا تکنولوژی ای، معمولا یک فرمت بهینه برای آن سیستم ارائه می‌شد، گستردگی توابع Encoding/Decoding به گستردگی توابع هش کننده و یا حتی بیشتر از آن است. به عنوان مثال ASCII،  Bas64، UTF16، UTF32 و ... همگی نمونه هایی از Encodingهای مختلف می‌باشند.

کاربردها:
اولین سوالی که ذهن با آن مواجه می‌شود این است که چرا باید Encodingهای مختلفی وجود داشته باشد؟
اگرچه دلایل زیادی برای به وجود آمدن انکدینگ های مختلف وجود دارد، اما دلیل اصلی آن عدم استاندارد سازی و استفاده از استانداردها در سال‌های ابتدایی تولد نرم افزارها و سیستم عامل‌ها و همچنین ایجاد قابلیت نمایش کاراکترهای خاص و کاراکترهای زبان‌های مختلف است. 
به عنوان مثال در ابتدا وقتی سیستم عامل‌ها توسعه داده شدند، هر تولیدکننده ای بدون توجه به آنچه که تولیدکننده ی دیگر ارائه می‌دهد یک Encoding برای خود به وجود آورد! همچنین کسی در نظر نگرفته بود که حروف فارسی یا چینی یا زبان های دیگر و همچنین کاراکترهای خاص عبارت های ریاضی نیز قرار است در آن محصول استفاده شود و بنابرین بسنده کرده بودند به حروف انگلیسی کوچک و بزرگ و چند علامت ساده‌ی ریاضی. از آنجا که تعداد این کاراکترها از تعداد حالت هایی که با 8 بیت می‌توان تولید کرد افزون نبود، بنابرین 1 بایت را به آن اختصاص دادند و نام آن انکدینگ را ASCII گذاشتند. بعدها با گذر زمان وقتی نیاز به کاراکترهای بیشتر احساس شد، انکدینگ دیگری ارائه کردند که طول آن بیشتر از یک بایت باشد و بتواند کاراکترهای بیشتری در خود جای دهد. این روال در گذر زمان منجر شد که Encodingهای مختلفی بوجود آید. (مانند Unicode, UTF-32 و ...).
یکی دیگر از دلایل، ناسازگاری استانداردهای موجود برای انتقال بعضی داده ها و انجام بعضی کارها بود. به عنوان مثال استاندارد شده بود که برای جداسازی قسمت های مختلف یک URL (آدرس وب) از کاراکتر "/" استفاده شود. همچنین برنامه نویس می‌توانست به گونه ای برنامه ی وب خود را بنویسد که پس از پر کردن یک فرم در صفحه توسط کاربر،محتویات آن فرم را از طریق Address-bar از وی دریافت کند.مشکلی که وجود داشت این بود که چنانچه کاربر در فرم خود از کاراکتر "/" استفاده می‌کرد، آنگاه حین ارسال این کاراکتر به سرور، به خاطد تداخل داده ی کاربر با کاراکتر جداکننده، با مشکل مواجه می‌شد. برای رفع این مسئله و چند مورد مشابه یک Encoding جدید به نام URL Encoding برای محتویات خط آدرس ارائه شد. در این سیستم جدید، کاراکترهای خاص نظیر / و فاصله و ' و " و ... پیش از ارسال به مقادیر دیگری تبدیل می‌شود (به ترتیب به 2F% و 20% و 27%  و 22%) که با استاندارد آدرس دهی تداخلی نداشته باشند و آنگاه در سرور Decode شده و تفسیر می‌شوند. 

انکدینگ‌های مشهور:
همانطور که در خلال متن اشاره شد، برای انکدینگ های مشهور می‌توان به سری UTF اشاره کرد که شامل کاراکترهای زبان فارسی و ... می‌باشد ؛ ASCII که تنها شامل کاراکترهای زبان انگلیسی و یک سری کاراکتر خاص است و همچنین Base64 که معمولا برای نمایش خروجی توابع رمزنگاری استفاده می شود. برای تبدیل داده های خود از یک انکدینگ به انکدینگ دیگر می‌توانید از ابزارهای آنلاین مانند این سایت استفاده کنید، یا این که با دانلود کردن نرم افزارهایی مثل ++Notepad از امکانات آنها برای تغییر Encoding  بهره ببرید.

حتما تابحال با صحنه ی خرچنگ قورباغه بودن زیرنویس فارسی دانلود شده یا دریافت ایمیلی با محتوایی ناخوانا مواجه شده اید. منشاء این ناخوانا بودن و خرچنگ قورباغه بودن، عدم تطابق Encoding مبدا و مقصد است.(سازنده ی زیرنویس یا ایمیل با سیستم شما). در قسمت بعدی به روش های رفع این مشکل می‌پردازیم.


خوشا آنانکه الله یارشان بی
بحمد و قل هو الله کارشان بی
خوشا آنانکه دایم در نمازند
بهشت جاودان بازارشان بی

۱۶ مهر ۹۴ ، ۰۵:۴۸ ۲ نظر موافقین ۱ مخالفین ۰
ابراهیم قاسمی

رمزنگاری-مقدمه/1-هَشینگ

خب، یکی از پیش نیازهایی که معمولا هم داخل برنامه نویسی، هم داخل کارهای مربوط به شبکه و امنیت و هم تو زمینه ی کار با کارت های هوشمند وجود داره، آشنایی با الگوریتم‌های رمزنگاری هست. پیش از این که به صورت خاص به الگوریتم های رمزنگاری بپردازیم، لازمه که با یک سری اصطلاحات و واژگان مختلفی که تو این زمینه استفاده میشه و با هم جابجا گرفته میشه، آشنا بشیم و کاربردهای هر کدوم رو بشناسیم:

  1. هش کردن (Hashing)
  2. کد کردن / از کد خارج کردن (Encoding & Decoding)
  3. رمز کردن / از رمز خارج کردن (Encrypting & Decrypting)

قسمت 1: "هش کردن یا دَرهم نگاری"

معرفی فرایند:
هش کردن، تولید یه متن از یه ورودی هست به نحوی که غیر قابل بازگشت باشه. یعنی از روی مقدار هَش، کسی نتونه داده ی اولیه رو بدست بیاره. چیزی که در مورد توابع درهم نگار (توابع هش کننده) باید بدونیم این هست که معمولا طول خروجی این توابع، مقدار ثابتی هست و این طول ثابت فارغ از طول ورودی است. سوال اولی که یه ذهن باهوش متوجه ش میشه این هست که بر این اساس، تابع های هش، توابع یک به یک نیستند. چرا که داشتن طول ثابت برای یه داده، به این معناست که تعداد حالت های محدودی میتونه داشته باشه (مثلا یه خروجی 4 بیتی، تعداد حالت هایی که میتونه داشته باشه 24 عدد است و ...)؛ در حالی که ورودی چون طول نامتناهی می تونه  داشته باشه، پس تعداد حالت هاش هم نا متناهی میشه، و بنابر این، اختصاص مقادیر هش به مقادیر ورودی نمیتونه یک به یک باشه. 
در جواب این سوال باید گفت که بله، نتیجه ی صحیحی گرفتید، به همین دلیل، توابع هش، یک به یک نیستند و هرچقدر که طول خروجی بزرگتر باشه، به یک-به-یک بودن نزدیک میشند(گرچه هیچ وقت نمیرسند!).

وقتی که قراره قدرت یه تابع/الگوریتم هَش کننده رو بررسی کنند، باید دو تا مسئله در نظر گرفته بشه:
  1. آیا با داشتن مقدار هَش یه داده، میتونیم داده رو بدست بیاریم؟
  2. آیا با داشتن یه مقدار هَش، میتونیم داده یا داده هایی تولید کنیم که با اون الگوریتم همین مقدار رو به ما بدهند؟
برای این که بتونیم تابع های هش رو حِس کنیم، من یه مثال فوق العاده ساده و قطعا فوق العاده ضعیف میزنم. فرض کنید که تابع هش ما به این صورت هست که یه رشته از ما میگیره و حروف جایگاه های فرد رو دور میریزه و از کنار هم گذاشتن پنج حرف اول مقادیر باقیمانده مقدار هش تولید میکنه. با این مثال ساده داریم:

Input 1:  HelloMyDearFriend
Input 2:  WhereDoYouWantToGO?

Step1 Of Hash(Input 1):  -e-l-M-D-a-F-i-n- 
Step1 Of Hash(Input 2):  -h-r-D-Y-u-a-t-o-o

Final Hash(Input 1): elMDa
Final Hash(Input 2): hrDYu

خب، همونطور که میبینیم، ما از ورودی های مختلف، خروجی های مختلفی به عنوان مقدار هَش شده بدست آوردیم که دیگه نمیتونیم مقدار اولیه رو از روی اون ها بدست بیاریم. ولی نکته ای که این الگوریتم داره اینه که، با داشتن مقدارهای هَش، خیلی ساده میتونیم داده ای بسازیم که بعد از پیاده سازی الگورتیم روی اون، همین خروجی تولید بشه. ضمنا بد نیست بدونیم که خروجی یک تابع هش رو Message Digest میگن.

کاربردها:
توابع هَش، دو تا کاربرد اصلی دارند:
  1. جایگزین پسورد برای ذخیره کردن در دیتابیس
  2. به عنوان Check Sum
اما هر کدوم از این ها چی هستند؟
جواب:
در مورد جایگزین پسورد برای دیتابیس: فرض کنید شما یه سایت راه اندازی کردید که برای دسترسی به یه قسمتی از سایت کاربرها باید اسم کاربری و کلمه ی عبور وارد کنند. خب، طبیعتا شما به عنوان مدیر سایت باید وقتی که کاربری قصد وارد شدن به سایت داره و نام کاربری و کلمه ی عبور خودش رو وارد میکنه، درست بودن این مقادیر رو بررسی کنید و تنها در صورت صحیح بودن، بهش اجازه ی ورود بدید. روش اولی که به ذهن میرسه اینه که، نام کاربری های مختلف رو با کلمه ی عبور مربوط به اونها داخل یه دیتابیس ذخیره کنید و هر بار مقادیر وارد شده رو با مقدارهای داخل دیتابیس مقایسه کنیم و الی آخر. 
خب، این روش درسته؛ ولی یه ایراد امنیتی داره. اون هم این که، در صورتی که کسی تونست یه قسمتی از سایت ما رو هک کنه، یا حتی خیلی ساده سرور ما رو دزدید، به راحتی میتونه با باز کردن دیتابیس، همه ی نام کاربری ها و پسوردها رو ببینه و از اونجا که معمولا افراد برای سایت های  مختلف کلمه های عبور یکسانی انتخاب میکنند، اطلاعات کاربر روی سایت های دیگه ای هم که عضوه، به خطر میفته.
خب کاربرد اول تابع های هَش اینجا خودش رو نشون میده. ما به عنوان برنامه نویس سایت، میایم به جای ذخیره کردن کلمه ی عبور، مقدار هَش شده ی اون رو داخل دیتا بیس ذخیره می‌کنیم. و از این به بعد هر بار که کاربر نام کاربری و کلمه ی عبور خودش رو وارد کرد، اول از کلمه ی عبور مقدار هَش رو بدست میاریم و بعد با مقدار داخل دیتابیس مقایسه میکنیم و الی آخر. با این مکانیزم، اگه سایت ما هک شد و کسی به نحوی به دیتابیس دست پیدا کرد، دیگه نمی تونه کلمه های عبور رو بدست بیاره. 

و اما در مورد Checksum: فرض کنید شما قصد دارید فایلی رو روی سایت خودتون بذارید که کاربرهای شما دانلود کنند و میخواید اطمینان داشته باشید که فایلی که دانلود میکنند، داخل مسیر، به صورت اتفاقی(به خاطر Noise)و یا به صورت تعمدی(توسط یه هکر) دستکاری نشده باشه؛ خب چه راهکاری به ذهنتون میرسه؟
ساده ترین راهکار اینه که از محتویات فایل یه مقدار هش شده تولید کنید و این مقدار هش شده رو روی سایت قرار بدید. حالا کاربرهای شما وقتی فایل رو دانلود کردند، قبل از این که اجراش کنند، با همون تابع هش شما، از محتویات مقدار هَش رو تولید می کنند و با مقدار روی سایت مقایسه می کنند. در صورتی که هر دو مقدار با هم برابر بودند، نتیجه می گیرند فایل داخل مسیر عوض نشده.

الگوریتم های مشهور:
SHA - MD5 - NT - LM  ....

توجه: بین hash و checksum و CRC  علیرغم شباهت های زیاد، تفاوت هایی هم هست که برای اطلاع از اونها به ویکی پدیا مراجعه کنید. (:


احسان هنری نیست به امید تلافی
نیکی به کسی کن که به کار تو نیاید ...
#صائب
۱۳ مهر ۹۴ ، ۲۲:۰۳ ۲ نظر موافقین ۱ مخالفین ۰
ابراهیم قاسمی