چرا نباید در زمینهء امنیت و رمزنگاری از خودمان الگوریتم اختراع کنیم!

در این زمینه یه عبارت یا عبارتهای معروف مشابهی هست.
میتونید این عبارت رو در گوگل سرچ کنید تا براتون کلی نتیجه بیاره: don’t roll your own crypto
من سعی میکنم چند توضیح خوب در این مورد رو پیدا و ترجمه کنم.

مثلا در این منبع: http://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own

یک نفر به پرسشی در این زمینه اینطور پاسخ داده (در بخش کامنت ها):

تعدادی افرادی که فکر میکردند بقدر کافی میدانند جمع شدند و یک روش رمزگذاری بنام WEP را برای شبکه های بی سیم ایجاد کردند. شما میتوانید WEP را در فقط چند دقیقه بشکنید. یک روش «مال خودتان را درست کنید» استفاده شده بود.

یک پاسخ دیگر:

شما میتوانید مال خودتان را درست کنید، اما اگر یک متخصص در امنیت/رمزنگاری نباشید یا روشتان توسط چند متخصص تحلیل نشود، احتمالا مرتکب یک اشتباه بزرگ امنیتی خواهید شدید. من بیشتر مایل هستم که روی یک روش رمزگذاری بازمتن که بصورت عمومی شناخته شده است و همه میتوانند آن را ببینند و تحلیل کنند شرط بندی کنم. چشمهای بیشتر به معنای احتمال کمتر آن است که نسخهء جاری آسیب پذیری مهمی داشته باشد نسبت به چیزی که در خانه توسط غیرمتخصصان توسعه داده شده است.
Phil Zimmermann (مخترع PGP) در کتاب آشنایی با رمزنگاری (صفحه 54) میگوید: «وقتی من در اوایل دهه 1970 در دبیرستان بودم، یک چیزی را طراحی کردم که فکر میکردم یک روش رمزگذاری نبوغ آمیز است. یک جریان عددی شبه رندوم به جریان متنی اضافه میشد تا یک متن رمزی را ایجاد کند. بنظر میرسید که این هر نوع تحلیل فرکانس متن رمزی را عقیم میگذارد، و حتی برای مجهزترین آژانس های امنیتی حکومت غیرقابل شکستن خواهد بود. من از این دستاورد خودم بسیار خرسند بودم.
سالها بعد، روش یکسانی را در چندین کتاب مقدماتی و مقاله های خودآموز رمزنگاری کشف کردم. چقدر جالب. دیگر رمزنگارها به روش یکسانی فکر کرده بودند. متاسفانه، آن روش بعنوان یک تمرین در خانه دربارهء اینکه چطور میتوان تحلیل های ابتدایی را برای شکستن آن بسادگی استفاده کرد مطرح شده بود. این برای روش نبوغ آمیز من خیلی زیاد بود.
من از این تجربهء فروتن کننده آموختم که چقدر ساده است که هنگام طراحی یک الگوریتم رمزنگاری به یک توهم اشتباه از امنیت دچار شد. بیشتر مردم درنمی یابند که چقدر بطور شیطانی ای دشوار است که یک الگوریتم رمزنگاری طراحی کرد که بتواند دربرابر یک حملهء طولانی و مصمم از جانب یک دشمن کاردان/مجهز مقاومت کند.»

اگر شما دربارهء «الگوریتم رمزنگاری خودتان را درست نکنید» قانع نشده اید، پس شما احتمالا یک متخصص نیستید و اشتباهات بسیاری وجود دارند که احتمالا مرتکب خواهید شد.

منبع: http://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own

—————————————

Bruce Scheier در 1998 نوشت:
هرکس، از نادان ترین آماتور تا بهترین متخصص رمزنگاری، میتواند الگوریتمی ایجاد کند که خودش نتواند بشکند. آن حتی سخت نیست. آنچه سخت است درست کردن الگوریتمی است که هیچ کس دیگری حتی بعد از سالها تحلیل نتواند بشکند. و تنها راه اثبات آن، در معرض گذاشتن الگوریتم برای سالها تحلیل بوسیلهء بهترین متخصصان رمزنگاری که پیدا میشوند است.

————————————-

«اجزاء اولیه رمزنگاری» الگوریتم های رمزنگاری بخوبی جا افتاده و سطح پایینی هستند که بصورت مکرر برای ساخت پروتکل های امنیتی یا سیستمهای امنیت رایانه استفاده میشوند. این روتین ها شامل، ولی نه محدود به، توابع هش یک طرفه و توابع رمزگذاری هستند.
در هنگام ایجاد سیستمهای رمزنگاری، طراحان اجزاء اولیه را بعنوان پایه ای ترین بلاک های سازنده خودشان استفاده میکنند. بخاطر این، اجزاء اولیه برای انجام یک وظیفهء خیلی خاص به شکلی با حد بالایی از اطمینان طراحی میشوند.
از آنجاییکه اجزاء اولیه بعنوان بلاک های سازنده استفاده میشوند، آنها باید بسیار قابل اطمینان باشند، یعنی مطابق مستندات فنی خود عمل کنند. برای مثال، اگر یک روتین رمزگذاری ادعا کند که فقط با تعداد X عملیات رایانه قابل شکستن است، سپس اگر آن بتواند با مقداری به حد قابل توجهی کمتر عملیات شکسته شود، گفته میشود که آن جزء اولیه شکسته شده است. اگر یک جزء اولیه شکسته شود، تقریبا هر پروتکلی که از آن استفاده میکند آسیب پذیر میشود. از آنجاییکه ایجاد روتین های رمزنگاری بسیار دشوار است، و تست آنها برای قابلیت اطمینان زمان طولانی ای میطلبد، اساسا نامعقول (و همچنین ناامن) است که برای تامین نیازهای یک سیستم رمزنگاری جدید یک جزء اولیه جدید طراحی شود. دلایل آن شامل این موارد میشود:

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

اجزاء اولیه رمزنگاری از بعضی جهات به زبانهای برنامه نویسی شباهت دارند. یک برنامه نویس رایانه به ندرت وقتی که یک برنامهء جدید مینویسد یک زبان برنامه نویسی جدید اختراع میکند؛ بجایش، او یکی از زبانهای برنامه نویسی جاافتاده را برای برنامه نویسی استفاده میکند.

چند نمونه از اجزاء اولیه رمزنگاری متداول:

- توابع هش یک طرفه.
- رمزنگاری کلید خصوصی (م: متقارن).
- رمزنگاری کلید عمومی (م: نامتقارن).
- امضاهای دیجیتال.
- توابع تولید اعداد شبه رندوم امنیتی (CSPRNG).

اجزاء اولیه به خودی خودشان کاملا محدود هستند. آنها نمیتوانند به درستی بعنوان یک سیستم رمزنگاری تلقی شوند. برای نمونه، یک الگوریتم رمزگذاری به تنهایی، امکان احراز هویت یا چک کردن دست نخوردگی پیام را در اختیار نمیگذارد.
وقتی اجزاء اولیه در پروتکل های امنیتی ترکیب میشوند، بیش از یک نیاز امنیتی میتواند پاسخ داده شود. برای مثال، برای ارسال یک پیام که نه تنها رمز شده است بلکه همچنین از دستکاری محافظت شده است، یک الگوریتم رمزگذاری همچون DES و یک روتین هش همچون SHA1 میتوانند در ترکیب با هم استفاده شوند. اگر حمله کننده کلید رمزگذاری را نداند، او نمیتواند پیام را طوری دستکاری کند که اثرانگشت آن معتبر باشد.
ترکیب اجراء اولیه رمزنگاری برای ساختن یک پروتکل امنیتی خودش یک تخصص کامل است. بیشتر خطاهای قابل سوء استفاده (یعنی عدم امنیت ها در سیستمهای رمزنگاری)، نه بخاطر خطاهای طراحی در اجزاء اولیه (همیشه با این فرض که آنها با احتیاط انتخاب شده اند)، بلکه بخاطر شکلی که آنها استفاده میشوند است. یعنی طراحی بد پروتکل و پیاده سازی باگ دار یا نه بقدر کافی با احتیاط.
تحلیل ریاضی پروتکل ها، در زمان نوشتن این مقاله، بلوغ نیافته است. بعضی ویژگیهای پایه وجود دارند که میتوانند بوسیلهء روشهای خودکار تصدیق شوند. حتی روشهایی برای تصدیق کامل وجود دارند، اما آنها فوق العاده سنگین هستند و نمیتوانند خودکار شوند. طراحی پروتکل یک هنر است که نیاز به دانش عمیق و تجربهء بسیار دارد؛ حتی پس از آن، اشتباهات متداول هستند.

منبع: http://en.wikipedia.org/wiki/Cryptographic_primitive

13 دیدگاه در “چرا نباید در زمینهء امنیت و رمزنگاری از خودمان الگوریتم اختراع کنیم!

  1. سلام

    کاش میشد یک خبرنامه میگذاشتین :|

    یکم سایتتون مخفی کاری داره ولی خوب حقم دارید این همه الاعات مفت و مجانی !

    ولی من این رو همیشه به خودم میگم که اخرش به کجا چنین شتابان !

    روز و شب خوش

      • مخفی کاری؟ متوجه نشدم! یعنی چی؟
        نه منظور بدی نداشتم.

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

  2. وای چقدر من نظر میدم و سوال میکنم :|
    اما سوالاتی در ذهن کوچیک بنده اینور و اونور میرن و جواب می خواهن
    اول اینکه ما رمز عبور کاربرامون را به این دلیل هش مکنیم که اگر زمانی دیتابیس هک شد اطلاعات کاربر دست هکر نیافتد ؟ آیا این درست هست ؟
    منتظر جواب هستم تا سوال بعدی را بپرسم…

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

        • وجود salt برای جلوگیری یا دشوار کردن یکسری از حمله ها ضروری است. به ازای هر پسورد/هش باید یک سالت رندوم داشته باشید. این salt رو معمولا در دیتابیس کنار هر هش نگهداری میکنن یا اصلا به خود هش الصاق میشه (مثلا هش های bcrypt اینطوری هستن) و بنابراین هردوی هش و سالت در یک فیلد ذخیره میشن.
          علاوه بر این میتونید یک سالت ثابت برای کل سایت (برای تمام هشها) که محرمانه است (در جایی غیر از دیتابیسی که هش ها درش هستن ذخیره میشه) هم داشته باشید که بهش pepper گفته میشه.
          وجود salt ضروریه داره، ولی اهمیت pepper بطور معمول کمتره و خیلی سایتها و سیستمها ممکنه اصلا از pepper استفاده نکنن.

          • خوب
            باید فلفل خیلی بهتر از نمک باشد.
            حالا نگهداری خود pepper هم مسائل امنیتی خودشو داره.
            من میخواستم کلا ایده ذیل رو بگم :
            {
            من میگم یک الگوریتمی باشه که با توجه به خود رشته یک salt اضافه کند. یعنی هر رشته یک salt !
            و با خودش الحاق بشه و salt برای هر رشته متامیز هست
            }
            اما مثل اینکه bcrypt این کار را انجام می دهد.
            باز هم ممنون.

  3. فلفل کاربرد خودش رو داره، سالت هم کاربرد خودش رو داره. مشکل pepper اینه که باید محرمانه نگه داشته بشه و به دست هکرها نیفته، وگرنه هیچ خاصیتی نخواهد داشت. محرمانه نگه داشتن چیزها درصورت بروز نفوذ و هک شدن هم کار راحتی نیست و خیلی وقتا عملا غیرممکنه. ضمنا pepper دردسر و پیچیدگی فنی اضافه میکنه که یکیش اینه که هش های موجود در دیتابیس به pepper وابسته هستن و بدون اون قابل استفاده نیستن، بنابراین شما وقتی از دیتا و دیتابیس خودتون بکاپ میگیرید، باید از pepper مربوط به اونا هم نسخهء پشتیبان تهیه کنید، اما طبیعتا pepper رو بهتره جدا از بکاپ دیتابیس نگهداری کنید، و این خودش باز یک دردسر و پیچیدگی اضافه میشه. خلاصه این دردسرها و پیچیدگی های فنی رو داره، در عین حالی که در خیلی موارد بالاخره دست هکرها میفته و نمیتونه نقش خودش رو ایفا کنه (ولی در خیلی موارد هم ممکنه اینطور نشه، بنابراین بنظر بنده شخصا بهتره pepper هم داشته باشیم). pepper درواقع یک کلید محرمانه است، و کلیدها هم مسائل مدیریت کلید رو دارن. کلا هرچی اجزای محرمانه در سیستم کمتر باشه، از نظر کاهش پیچیدگی و دردسرهای فنی و مشکلات و خطاهای انسانی، بهتره. البته تعداد این اجزای محرمانه یک حداقلی داره، چون دیگه از یک حداقلی کمتر نمیشه امنیت لازم رو بدست آورد.

  4. salt و pepper از نظر اصولش باید رندوم باشن. فقط با دانستن پسورد و یه چیزهایی مثل نام کاربری و اینها نباید بشه salt رو محاسبه کرد یا به یک تعداد کمی از مقدارهای ممکن که توسط هکرها قابل محاسبه در زمان نسبتا کمی باشه محدودش کرد. چون اینطوری هکرها هم میتونن قبل از اینکه به دیتابیس خاصی دسترسی پیدا کنن، هش یکسری پسوردهای متداول رو از پیش محاسبه و ذخیره کنن و بعد هم روی هر برنامه ای که از این روش استفاده کرده باشه اون هش ها رو تست و مقایسه کنن (بدون اینکه نیاز باشه همه رو دوباره محاسبه کنن). یعنی اینطوری شما یک مزیت به هکرها دادید. درواقع دو مزیت! یکی اینکه بتونن از قبل و بدون دسترسی به هش ها، روی کرک اونا کار کنن، دیگری اینکه بتونن یکسری هش رو فقط یک بار محاسبه و ذخیره کنن و بعد اونا رو روی چند برنامه/سایت استفاده کنن.
    برای تولید چیزهایی مثل سالت، حتی الامکان باید از توابع رندوم امنیتی استفاده کرد (از نظر اصولش، استفاده از توابعی مثل mt_rand, uniqid و پارامترهایی مثل زمان (تابع microtime)، به تنهایی چندان اصولی و امن نیست؛ چون این توابع و پارامترها برای کاربردهای امنیتی طراحی نشدن و آنتروپی اونا هم زیاد نیست).
    باید از یک تابع رندوم مخصوص کاربردهای امنیتی مثل تابعی که در اینجا معرفی کردم استفاده کرد: http://www.hamidreza-mz2.tk/?p=649

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

*

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>