PDA

View Full Version : طول کلیدها



eshpilen
جمعه 26 اسفند 1390, 19:50 عصر
میدونید که رشته های رندوم که ما در اینجا اونها رو کلید مینامیم در برنامه نویسی وب خیلی کاربرد دارن.
بطور مثال میتونیم موقع ثبت نام یک کلید برای لاگین خودکار کاربر درنظر بگیریم و موقع لاگین اون رو در کوکی ذخیره کنیم که به این شکل هربار دیگر که کاربر از سایت بازدید میکنه میتونیم مقدار کلید موجود در کوکی رو بخونیم و اگر با کلید متناظر برای اون کاربر در دیتابیس تطابق داشت کاربر رو بصورت خودکار لاگین کنیم.
کاربرد دیگر کلیدها در ایمیل فعال سازی اکانت هست بطور مثال.
کاربرد دیگر در Reset کردن پسورده.

با فرض اینکه کاراکترهای کلید بصورت بقدر کافی رندوم انتخاب میشن سوال اینه که یک کلید امن باید دقیقا چه خصوصیاتی داشته باشه.

بنده اینطور محاسبه کردم:

فرض کنید کلید از حروف انگلیسی کوچک و بزرگ و اعداد تشکیل شده.
بنابراین تعداد حالتهای ممکن چنین کلیدی اینطور محاسبه میشه:

(26+26+10)^n
معادل:

62^n
چون هر کاراکتر میتونه از بین 26 حرف کوچک، 26 حرف بزرگ، و 10 رقم انتخاب بشه.
n هم طول کلید، یعنی تعداد کاراکترهاش، است.

از اونجایی که در علم رمزنگاری حداقل طول کلید استاندارد 128 بیت است، بنده n رو مقداری گرفتم که تعداد حالتهای ممکن کلید از تعداد حالتهای ممکن یک کلید باینری 128 بیتی کمتر نباشه.

تعداد حالتهای یک کلید 128 بیتی باینری اینطور محاسبه میشه:

2^128
که تقریبا میشه 3.4e+38

اگر ما طول کلید خودمون رو 22 کاراکتر بگیریم، تعداد حالتهاش میشه:

62^22
که تقریبا برابر است با 2.7e+39

همونطور که میبینید، تعداد حالتهای کلید ما حتی از کلید 128 باینری هم بیشتره، ولی چون اگر بجای 22 کاراکتر 21 کاراکتر درنظر بگیریم تعداد حالتهاش میشه 4.3e+37 که از تعداد حالتهای کلید 128 بیتی کمتره بنابراین طول کلید خودمون رو 22 کاراکتر انتخاب کردیم.

حالا یک مثال از میزان استحکام این کلید میزنم:

فرض کنید یک کرکر بتونه در هر ثانیه 100 هزار درخواست به سرور بفرسته و جواب بگیره. حالا حساب میکنیم که برای تست کردن نیمی از بازهء حالتهای ممکن برای کلید ما به چقدر زمان نیاز داره (*):

(62^22)/2/100000/60/60/24/365=429319452023506532263169320
زمان رو بر حسب سال بدست آوردم که تقریبا میشه 429319452023506532263169320 سال!

*: در علم رمزنگاری در محاسبات مربوط به Brute-force، زمان لازم برای تست نیمی از بازهء مورد نظر رو محاسبه میکن، نه کل بازه رو.

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

ما فرض کردیم کرکر بتونه در هر ثانیه 100 هزار کلید رو چک کنه، که احتمالا این در عمل فقط روی سرورها و سایتهای بزرگ که میتونن این ترافیک رو جواب بدن ممکنه، ولی بهرحال نباید چیزی رو دست کم گرفت و روی امنیت ریسک کرد؛ بخصوص که محکم کاری بیشتر در اون هزینهء آنچنانی هم نداره.

درمورد عملی بودن این حمله از سمت کرکر هم باید بگم که حمله مورد نظر میتونه با Botnet انجام بشه که Botnet های واقعا بزرگی وجود دارن که احتمالا میتونن چند ده میلیون درخواست در هر ثانیه ارسال و دریافت کنن (البته با فرض اینکه سایت مورد نظر هم بتونه این تعداد درخواست رو جواب بده). ولی بازهم واضحه که بازهء کلید ما اونقدری بزرگه که حتی با چندصد میلیارد تست بر هر ثانیه هم نمیتونن کلید ما رو کرک کنن.

تازه در کاربردهایی که کلید مورد نظر فقط برای زمان محدودی مثل 24 ساعت یا چند روز اعتبار داره (مثلا در ایمیل فعال سازی یا ریست کردن پسورد)، امکان کرک کردن بسیار محدودتر میشه.

امیدوارم در محاسبات اشتباهی نکرده باشم.
اگر اشتباهی بود تذکر بدید.

نکتهء مهمی که باید در پایان بگم اینه که در این تاپیک ما خواستیم خصوصیات کلید رو بصورت تئوریک و در شرایط ایدئال بررسی کنیم، یعنی به شرطی که واقعا یک کلید رندوم به معنای بقدر کافی واقعی داشته باشیم. اینکه در عمل این قضیه تا چه حد برقرار است یک بحث و موضوع جالب دیگری است که انشاا... بعدا براش تاپیک جداگانه ای تاسیس میکنیم. فقط پیشاپیش هشدار بدم که توابعی مثل rand و mt_rand و یکسری روشهای متداولی که توسط بیشتر یا حداقل خیلی از برنامه نویسان برای تولید کلید استفاده میشن خیلی ضعیفتر از شرایط ایدئال ما هستن و محاسبات ما درمورد امنیت اونها به هیچ وجه صدق نمیکنه. پس موضوع جالب، ظریف، کاربردی، و بسیار مهم بعدی این خواهد بود که چطور یک کلید بقدر کافی رندوم ایجاد کنیم.

eshpilen
جمعه 26 اسفند 1390, 23:18 عصر
اگر شد در مورد /dev/urandom هم یه توضیح بده درمورد dev/urandom که قبلا توضیح داده بودم در تاپیک دیگری.
در این پست فکر میکنم توضیح کافی داده باشم: پست شماره 35 تاپیک ذخیرهء امن پسورد کاربران (http://forum.iranphp.org/Thread-%D8%B0%D8%AE%DB%8C%D8%B1%D9%87%D8%A1-%D8%A7%D9%85%D9%86-%D9%BE%D8%B3%D9%88%D8%B1%D8%AF-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%A7%D9%86?pid=265 23#pid26523)

ضمنا همونطور که گفتم تولید اعداد رندوم با کیفیت کافی که قابل مصرف در حیطهء امنیت و رمزنگاری باشن خودش یک موضوع جداگانه میطلبه و اینطور چیزها هم به همون بحث مربوط میشه.
در این تاپیک فقط میخواستم روی خصوصیات کلید با فرض اینکه منبع رندوم قابل اتکایی داشته باشیم همفکری کنیم. بعدش باید بریم سراغ تهیهء منبع رندوم مناسب. چون تا وقتی منبع رندوم مناسب نداشته باشیم تعداد حالتهای کلید هرچی هم در ظاهر زیاد باشه فایده نداره. مگر اینکه یک راهکارهای جانبی ای هم مثل محدودیت های زمانی بهش اضافه کنیم که خب اینم همیشه کار راحت و کم هزینه ای نیست و نهایتا هم ممکنه دچار ابهام و تزلزل قابل توجهی باشه.

فقط بگم الان یکسری بررسی مجدد و محاسبه انجام دادم متوجه شدم وضعیت در این زمینه واقعا خرابه!
متاسفانه منابع رندوم با کیفیت در خیلی از سرورها در دسترس نیستن و بیشتر برنامه نویسان هم از این امر و اینکه روشهایی که بکار میبرن امنیت بالایی ندارن آگاه نیستن. بعید نیست بعضی از موارد هک با استفاده از همین ضعف انجام میشن. چون حتی خودمم تاحالا در این مسئله اینقدر روشن نشده بودم باوجود این همه مطالعه و دقت!
مثلا متوجه شدم همون تابعی که در پست 35 معرفی کردم روی خیلی از سرورها نهایتا باید از mt_rand بعنوان fallback استفاده کنه. چون openssl_random_pseudo_bytes که بنظرم روی خیلی سرورها در دسترس نیست، و همچنین /dev/urandom. حتی روی خیلی از سرورهای لینوکس دسترسی به /dev/urandom وجود نداره احتمالا، چون open_basedir احتمالا اجازهء دسترسی به دایرکتوری /dev رو نمیده.

الان کانکت شدم داشتم میرفتم سراغ سایت پشتیبانی phpseclib که یه پیشنهادی بدم و همفکری ای بکنم که شاید بشه یه مقداری کیفیت رندوم رو بالا برد.
ضمنا روشهای دیگری هم در ذهنم هست مثل گرفتن آنتروپی از دیتابیس و همچنین خود صاحب سایت موقع نصب برنامه.