حفاظت از دموکراسی با رمزنگاری و توابع درهم‌ساز

محتوی این نوشته برای اسفند ۱۳۹۴ است که به دلیل انتقال وبلاگم به ویرگول دوباره بازنشر می‌کنم.

مدت‌ها بود خبرهای زیادی در مورد الکترونیکی شدن انتخابات می‌شنیدیم، اتفاقی که در نهایت با مخالفت شورای نگهبان اتفاق نیفتاد. فکری که ذهن من‌ رو مشغول کرده بود تضمین صحت و سلامت چنین انتخاباتی و یا در حالت کلی‌تر هر مدل از انتخابات‌ها بود، طوری که امکان هرگونه دستکاری در نتیاج و داده‌سازی از بین بره و حتی کسی نتونه ادعا کنه به شخص دیگه‌ای رای داده و رای‌ش عوض شده. تا اینکه یک روز سر یک کلاس خواب‌آور تصمیم گرفتم یک روش براش پیدا کنم و در نهایت جواب داد (با تشکر از استاد که حرف‌های تکراری می‌زد)
قبل از گفتن روش بگذارید کمی در مورد رمزنگاری و هش بگم. به طور کلی الگوریتم‌های رمزنگاری به دو دسته تقسیم می‌شند، متقارن و نامتقارن. 
رمزنگاری متقارن: الگوریتم‌های این نوع رمزنگاری از یک کلید برای رمزگذاری و رمزگشایی استفاده می‌کنند، مثلا من و شما توافق می‌کنیم که پیام‌هامون رو با الگوریتم AES و کلید 123456789 رمز کنیم و برای هم بفرستیم، امنیت این روش به امنیت الگوریتم و دونستن کلید برمیگرده. یعنی هر کس دیگه‌ای که بدونه کلید پیام‌های ما 123456789 است می‌تونه پیام‌ها رو بخونه.
رمزنگاری نامتقارن: این الگوریتم‌ها از دو کلید استفاده می‌کنند، یکی برای رمزکردن و یکی برای رمزگشایی. نمونه معروف این نوع الگوریتم‌ها RSA است.  فرض کنید شما دوتا کلید به اسم A و B دارید، به طور استاندارد در این نوع الگوریتم‌ها قراره اگر پیامی با کلید A رمز شد، فقط با کلید B باز بشه و اگر با کلید B رمز شد، فقط با کلید A باز شه. (البته نمونه‌هایی هم هستند که فقط با یکی رمز و با یکی رمزگشایی می‌شند)

وقتی شما می‌خواهید از این الگوریتم‌ها استفاده کنید، دوتا کلید می‌سازید به اسم کلید عمومی و کلید خصوصی، کلید عمومی رو به همه می‌دید و کلید خصوصی رو پیش خودتون نگه می‌دارید.

کلید سبز رنگ کلید عمومی و کلید قرمز رنگ، کلید خصوصی است.
کلید سبز رنگ کلید عمومی و کلید قرمز رنگ، کلید خصوصی است.


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

ولی یک حالت دیگه هم وجود داره، من قراره مطمئن بشم که یک محتوی از سمت شما برای من میاد، مثلا می‌خوام مطمئن بشم که شما یک ایمیل رو فرستاید. شما متن رو با کلید قرمز رنگ رمز می‌کنید، این موقع من یا هر کس دیگه‌ای که کلید سبز رو داشته باشه مطمئن میشه که این محتوی رو واقعا خود شما فرستاید. نکته مهم اینکه شما نمی‌تونید منکر این موضوع بشید که فرستنده این محتوی نیستید. از این قضیه (رمزگذاری با کلید خصوصی) برای عدم انکار و امضای دیجیتال استفاده می‌شه. حتی در کشورهایی مثل آمریکا برای امضای قراردادها استفاده می‌شه و کاملا حقوقیه.
هش (Hash): هش یعنی توابع یک‌ طرفه، یعنی وقتی یک ورودی به یک تابع هش داده می‌شه خروجی ای تولید می‌کنه که با دونستن اون نمیشه به ورودی رسید. مثلا خروجی تابع md5 (یکی از توابع معروف هش) به ورودی Moein Hosseiniمیشه ca6e1e3c12c635146943e1c11c1502ae که یک‌طرفست، یعنی با دونستن ca6e1e3c12c635146943e1c11c1502ae نمیشه به Moein Hosseini رسید. به جز اینکه یک جدول بزرگ از همه ورودی‌ها درست کنید و هش اون‌ها رو حساب کنید (Rainbow table) که البته برای اینکه این‌هم سخت و تقریبا غیر ممکن بشه بهش چیزی به اسم salt اضافه میشه، یعنی من یک مقدار رندوم و به ورودی تابع هش اضافه می‌کنم، یعنی این‌سری Moein Hosseini s*2js1Je رو هش می‌کنم که باعث میشه ساخت Rainbow table خیلی بزرگ و غیر ممکن بشه.
خوب بریم سراغ دموکراسی، برای این روز این اصول رو داریم:
نکته: منظور از دولت برگذار کننده انتخابات است.
۱- رای هیچ کس نباید مشخص بشه (حتی برای دولت)، یعنی حریم خصوصی هر شخص باید حفظ بشه.
۲- دولت موظفه همه رای‌ها رو در یک جدول منتشر کنه، به‌صورتی که فقط شخص رای دهنده متوجه بشه کودوم سطر جدول متعلق به خودشه. (مثلا من بدونم اون سطری که خونه A اون برابر فلان هش است، رای منه)

یک نمونه از جدول انتشاری در دولت
یک نمونه از جدول انتشاری در دولت

۳- در صورت دستکاری نتایج، شخص بتونه اثبات کنه
۴- در صورتی که سطر مربوط به شخص منتشر نشد، بتونه اثبات کنه که رای داده
۵- شخص نتونه به صورت دروغین ادعا کنه که به کس دیگه‌ای رای داده و در جدول رای دیگه‌ای براش ثبت شده
حالا برای اینکه به موارد بالا برسیم، از راه حل زیر استفاده می‌کنیم.

روش تضمین عدم تقلب در انتخابات
روش تضمین عدم تقلب در انتخابات


قبل از شروع انتخابات دولت یک کلید خصوصی و عمومی برای انتخابات درست می‌کنه و کلید عمومی رو در اختیار همه قرار می‌ده، این یعنی اگر هر چیزی با کلید خصوصی رمز شد حتما توسط دولت رمز شده و دولت نمی‌تونه انکار کنه که این رو من رمز نکردم.
برای رای دادن هر شخص یک مقدار که فقط خودش می‌دونه انتخاب می‌کنه (مثل پسورد)، حالا از کد ملی و اون مقدار هش می‌گیره، بعد از اون هش و رای خودش ({hashValue:Vote}) رو برای دولت می‌فرسته.
دولت چیزی رو که دریافت کرده رو با کلید خصوصی انتخابات رمز می‌کنه و برای رای‌دهنده ارسال می‌کنه، رای دهنده مقدار دریافتی رو با کلید عمومی انتخابات رمزگشایی می‌کنه و مطمئن می‌شه که این مقدار توسط دولت ارسال شده و رای اون به درستی ثبت شده و مقدار دریافتی رو پیش خودش نگه می‌داره.
حالا بعد از انتشار جدول توسط دولت، در صورتی که رای کسی عوض شده باشه، شخص با ارائه مقدار رمزشده دریافتی از دولت می‌تونه اثبات کنه رای اون چیز دیگه‌ای بوده (چون با کلید خصوصی انتخابات رمز شده، دولت نمی‌تونه منکر بشه که اون رای رو دریافت نکرده)
اگر رای داده باشه و رای اون در جدول نباشه هم می‌تونه با ارائه همون متن رمزشده توسط دولت ادعا کنه که رای داده و دولت رای اون رو دریافت کرده
رای‌دهنده هم نمی‌تونه به دروغ بگه به شخص دیگه‌ای رای داده و تقلب شده، چون باید یک متن رمزشده با کلید خصوصی انتخابات داشته باشه که وقتی با کلید عمومی باز‌ میشه رای شخص در اون موجود باشه.
با مقدار هش موجود در جدول هم که هر شخص منحصرا هش خودش رو می‌دونه، حریم خصوصی اشخاص حفظ می‌شه.

پ.ن۱: بعد از نوشتن این پست متوجه شدم که الگوریتم‌های خیلی زیاد و خوبی برای این کار ارائه شده