نکات کلیدی
-
این روزها علاقه و توجه به اثباتهای دانایی صفر (Zero-Knowledge Proofs) بهویژه در زمینه سامانههای غیرمتمرکز مبتنی بر بلاکچین به شدت افزایش یافته است.
-
توضیح اثباتهای دانایی صفر کار سختی است، به همین دلیل اغلب مقالات یا مخاطبان اهل ریاضیات را هدف میگیرند یا مثالهایی بسیار محدود و خاص ارائه میکنند.
-
اثباتهای دانایی صفر میتوانند برای نشان دادن آگاهی از انواع راهحلهای مخفی بهکار بروند؛ مثلاً پیشتصویر یک تابع هش، کلید خصوصی متناظر با یک کلید عمومی، یا تراکنشهای مشخصی که یک بلاکچین را سالم نگه میدارند.
-
اثباتهای دانایی صفر میتوانند درستی و قابل اعتماد بودن یک روش را بدون افشای خود آن روش نشان دهند.
-
در ادامه، یک الگوریتم ساده میبینید که با استفاده از گیتهای منطقی میتواند برای هر مسئلهای که نیازمند پنهان کردن راز است، یک اثبات دانایی صفر بسازد.
اثباتهای دانایی صفر در سالهای اخیر به لطف ظهور سامانههای غیرمتمرکز مبتنی بر بلاکچین حسابی سر و صدا کردهاند. برای مثال، رمزارزهایی مثل ZCash و Monero با تکیه بر اثباتهای دانایی صفر، تراکنشهای خصوصی روی یک بلاکچین عمومی ارائه میکنند.
اما واقعاً این رمزنگاری «جادویی» که میتواند پاسخِ تقریباً هر نوع نیاز حریم خصوصی روی بلاکچین را فراهم کند، چیست؟ همانطور که انتظار میرود، کمبود مقاله درباره اینکه اثبات دانایی صفر چیست و چگونه کار میکند وجود ندارد.
با این حال، این مقالات معمولاً یا برای مخاطبان مجهز از نظر ریاضی نوشته میشوند، یا مثالهایی بسیار ساده از سیستمهای اثبات دانایی صفر تخصصی ارائه میکنند. منظور از تخصصی این است که فقط برای نوع خاصی از اثباتها طراحی شدهاند. سؤال این است: «با یک اثبات دانایی صفر چه چیزهایی را میتوان اثبات کرد؟» پاسخ کوتاه این است: «تقریباً همهچیز». پاسخ بلندتر کمی توضیح لازم دارد.
وقتی در زمینه رمزنگاری درباره «اثبات دانایی صفر» صحبت میکنیم، منظور ما اثباتِ دانستنِ راهحل مخفیِ یک مسئله (یا معما) است. این راهحل میتواند دانستن پیشتصویر یک تابع هش باشد، یا دانستن کلید خصوصی متناظر با یک کلید عمومی، یا دانستن مجموعهای از تراکنشهای مشخص که یک بلاکچین را از نظر صحت و تمامیت حفظ میکنند.
در این مقاله سعی میکنم شما را قانع کنم که میتوانید آگاهی از هر راهحل مخفی از این جنس را برای هر مسئلهای در قالب دانایی صفر اثبات کنید؛ یعنی بدون اینکه هیچ اطلاعاتی درباره خود آن راز افشا کنید. برای مثال، اگر آلیس پیشتصویر یک مقدار هش SHA256 مشخص را بداند، میتواند دانش خود را به باب اثبات کند بدون اینکه حتی یک بیت از آن پیشتصویر را به او بدهد.
یک مثال ساده
بیایید یک داستان خیالی را در نظر بگیریم. فرض کنید مری مخترع مکانیزمی برای تشخیص وجود مقدار بسیار کمی ناخالصی آرسنیک در فولاد است. او نمیخواهد روش خود را افشا کند، اما میخواهد بابت هر تست از صنعت پول دریافت کند. تام مدیر یک کارخانه فولاد است که هیچ دلیلی ندارد روش مری را قبول کند. اما اگر روش او درست باشد، تام دوست دارد خدماتش را بخرد. مری چطور میتواند تام را قانع کند که روشش صددرصد قابل اعتماد است، بدون اینکه افشا کند چگونه این کار را انجام میدهد؟
مری پیشنهاد زیر را مطرح میکند:
تام ۱۲۸ نمونه آماده میکند که هر کدام یا فولاد خالص هستند یا فولادی با میزان مشخصی ناخالصی آرسنیک، و این انتخاب را بر اساس پرتاب سکه انجام میدهد. برای هر نمونه، تام سکه میاندازد؛ اگر رو بیاید، آن نمونه فولاد خالص است، و اگر پشت بیاید آن نمونه فولاد همراه با ناخالصی آرسنیک است. او روی کاغذ ثبت میکند که کدام نمونه از کدام نوع است، و سپس نمونهها را به مری تحویل میدهد. مری فقط شناسه نمونهها را میبیند و نمیداند کدامیک ناخالصی دارد. حالا وظیفه او این است که بگوید هر نمونه از کدام نوع است، و تام در صورتی اثبات او را میپذیرد که در تمام موارد پاسخ او درست باشد. اگر مری هیچ روش قابل اعتمادی نداشته باشد و فقط شانسی حدس بزند، احتمال اینکه در تمام نمونهها درست حدس بزند فقط برابر با ۲⁻¹²⁸ است که عددی بسیار کوچک است. بنابراین اگر مری در همه نمونهها درست بگوید، تام دلیل کافی دارد که باور کند او روشی برای تمایز نمونههای خالص و ناخالص دارد.
این یک نمونه از اثبات دانایی صفر است. مری توانست تام را قانع کند که روشش کار میکند، بدون اینکه افشا کند چگونه این کار را انجام میدهد. سؤال این است که چه نوع اثباتهایی را میتوان بهصورت دانایی صفر ارائه کرد. پاسخ این است که تقریباً هر چیزی که بتوان آن را اثبات کرد، میتوان در قالب دانایی صفر هم اثبات کرد. فرض کنید راهحل یک معما را در اختیار دارید یا کلید خصوصی متناظر با یک کلید عمومی را میدانید؛ تمام این موارد را میتوان در قالب دانایی صفر اثبات کرد، یعنی بدون اینکه راهحل معما یا کلید خصوصیتان را افشا کنید.
در این مقاله سعی میکنیم ببینیم این کار چگونه ممکن است، بدون اینکه وارد ریاضیات موردنیاز برای سیستمهای اثبات دانایی صفر کارآمدی شویم که در صنعت مورد استفاده قرار میگیرند.
قرار ملاقات (Blind Dates)
حالا یک سناریوی متفاوت را در نظر بگیریم. مری و تام به یک قرار ملاقات (Blind Date) رفتهاند و حالا میخواهند تصمیم بگیرند که آیا دوست دارند به قرار دوم هم بروند یا نه. با این حال، بدجور awkward میشود اگر یکی از آنها بخواهد قرار دوم را داشته باشد اما دیگری نخواهد. پس باید به روشی از هم سؤال کنند که اگر یکی از آنها بخواهد برود، طرف مقابل فقط در صورتی متوجه این موضوع بشود که خودش هم بخواهد برود.
در اصل، ما میخواهیم یک گیت AND پیادهسازی کنیم؛ به این شکل که «خواستنِ رفتن» هر نفر با ورودی ۱ و «نخواستن» با ورودی ۰ نمایش داده میشود. اگر خروجی گیت AND برابر ۱ باشد، یعنی هر دو ورودی باید ۱ بوده باشند، پس هر دو میخواهند بروند. اما هیچکدام نباید بتواند چیزی بیشتر از آنچه از ورودی خودش و نتیجه نهایی محاسبه به دست میآید، درباره ورودی دیگری بفهمد.
چطور میتوانیم به این هدف برسیم؟ فرض کنیم که هر دو صادق هستند، یعنی کارهایی را که از آنها انتظار میرود انجام میدهند، ولی در عین حال تمایل دارند هر چیزی را که میبینند به خاطر بسپارند. یک راهحل میتواند به شکل زیر باشد.
برای هر مقدار ممکنِ هر ورودی به گیت AND، یک کلید در نظر میگیریم. اگر تام مقدار ۰ را انتخاب کند، ورودی او با کلید
K₀ᵀ
نمایش داده میشود؛ و اگر مقدار ۱ را بدهد، ورودی او با کلید
K₁ᵀ
نمایش داده میشود. بالانویسها (۰ و ۱) فقط نشان میدهند کلید متناظر با کدام مقدار است و توان ریاضی نیستند. بهطور مشابه، ورودیهای مری با K₀ᴹ و K₁ᴹ برای ۰ و ۱ نمایش داده میشوند.
حالا چهار جعبه داریم که هر کدام فقط با استفاده از دو کلید با هم باز میشوند: یک کلید از کلیدهای تام و یکی از کلیدهای مری. جعبهها به این صورت تعریف میشوند:
-
جعبه B₀ با استفاده از کلیدهای K₀ᵀ و K₀ᴹ با هم باز میشود.
-
جعبه B₁ با استفاده از K₀ᵀ و K₁ᴹ باز میشود.
-
جعبه B₂ با استفاده از K₁ᵀ و K₀ᴹ باز میشود.
-
جعبه B₃ با استفاده از K₁ᵀ و K₁ᴹ باز میشود.
ظاهر بیرونی همه جعبهها یکسان است، اما داخل هر کدام یک تکه کاغذ است که روی آن یک مقدار نوشته شده است. درون جعبههای B₀، B₁ و B₂، روی کاغذ عدد ۰ نوشته شده است، و درون B₃ عدد ۱.
حالا اگر تام بتواند به نحوی کلید متناظر با ورودی خودش را فراهم کند و مری هم همینطور، هر کدام از آنها میتوانند جعبهای را که با آن دو کلید باز میشود، پیدا و باز کنند (با امتحان کردن هر جعبه با آن جفت کلید) و نتیجه تصمیمشان را بفهمند. این فرآیند، ورودی طرف مقابل را به دیگری افشا نمیکند، چون کلیدها برچسبی ندارند که نشان بدهد هر کدام متناظر با چه مقداری هستند و ظاهر بیرونی جعبهها هم یکسان است.
هرکدام از آنها میتواند مسئول باز کردن جعبه باشد، به شرطی که فقط اجازه داشته باشد یک کلید از کلیدهای خودش را امتحان کند. اگر اجازه داشته باشد هر دو کلید خود را امتحان کند، میتواند بفهمد ورودی طرف مقابل چه بوده است.
در ابتدای پروتکل، یکی از آن دو باید جعبهها و کلیدها را بسازد. فرض کنیم تام این کار را انجام میدهد. در این صورت او تمام مقادیر و معنای هر کلید را میداند. بنابراین اگر اجازه داشته باشد ببیند مری کدام کلید را انتخاب میکند، او تصمیم مری را خواهد دانست. پس اگر تام جعبهها و کلیدها را میسازد، این مری است که باید جعبه را باز کند.
حالا باید راهی وجود داشته باشد تا تام بتواند کلید متناظر با انتخاب مری را به او بدهد بهگونهای که مری فقط همان کلید را بگیرد و تام هیچ راهی برای فهمیدن اینکه او کدام کلید را انتخاب کرده نداشته باشد.
توجه کنید که تام نباید هر دو کلید مری را به او بدهد، چون در آن صورت مری میتواند تابع را برای هر دو ورودیِ ممکن خودش محاسبه کند و این کار ورودی تام را برای او افشا خواهد کرد. بنابراین تام هر یک از کلیدهای مری را در یک پاکت جداگانه قرار میدهد و روی هر کدام برچسبی میزند که به مری بگوید کدام مربوط به ۰ و کدام مربوط به ۱ است. مری پاکتی را که با انتخاب خودش تطابق دارد باز میکند و برچسب پاکت دیگر را جدا میکند.
سپس آنها پاکتِ بازنشده را بهطور عمومی نابود میکنند و مری جعبهای را باز میکند که با کلیدی که تام داده و کلید خودش باز میشود. عددی که روی تکه کاغذ داخل جعبه نوشته شده، پاسخ است که مری آن را به تام نشان میدهد. اگر تام همه کاغذها داخل جعبهها را امضا کرده باشد، مری هیچ راهی برای تقلب با جایگزین کردن کاغذها با برگه خودش نخواهد داشت. با این حال، تام میتواند با دستکاری نحوه ساخت جعبهها تقلب کند.
برای مثال، تام میتواند همه جعبهها را طوری بسازد که روی هر کاغذ عدد ۱ نوشته شده باشد. در این صورت، خروجی همیشه ۱ خواهد بود، بدون توجه به ورودیها. با این حال، در اینجا فرض کردهایم که تام کنجکاو است اما صادق.
حالا که دیدیم چطور میتوان یک پروتکل برای یک گیت AND ساخت، ادامه کار (و اعمال تغییرات لازم) برای پیادهسازی یک گیت XOR و یک گیت OR را به خواننده واگذار میکنم.
رأیگیری سهنفره
حال سناریوی دیگری را در نظر بگیریم. تام، دیک و هری میخواهند تصمیم بگیرند برای تعطیلات به کدام مقصد سفر کنند. دو گزینه دارند: ۰ و ۱. آنها تصمیم میگیرند مقصد را بر اساس رأی اکثریت تعیین کنند. چطور میتوانیم برای رأی اکثریت یک مدار بولی بسازیم؟ مدار زیر، رفتاری مطابق با نیاز ما دارد:
(T∧H)∨(H∧D)∨(D∧T)(T \land H) \lor (H \land D) \lor (D \land T)
در اینجا T ورودی تام، D ورودی دیک و H ورودی هری است، که در آن
∧\land نشاندهنده گیت AND و ∨\lor نشاندهنده گیت OR است.
اگر مقدار این فرمول ۱ شود، دستکم یکی از عبارتهای داخل پرانتز باید مقدار ۱ داشته باشد؛ در نتیجه دستکم دو تا از ورودیها باید ۱ باشند. پس رأیگیری ما را میتوان با مداری شامل سه گیت AND و دو گیت OR ارزیابی کرد.
حالا فرض کنیم میخواهیم مطمئن شویم افراد متوجه نشوند چه کسی به گزینه کمتر محبوب رأی داده است. برای رسیدن به این هدف میتوانیم از همان روش جعبهها و کلیدها که قبلاً دیدیم استفاده کنیم؛ اما در اینجا لازم است خروجی گیتهای AND را بهعنوان ورودیهای گیتهای OR به کار ببریم.
این کار بسیار ساده است: به جای اینکه در جعبهها تکه کاغذهایی با عدد ۰ یا ۱ قرار دهیم، کلیدهایی را قرار میدهیم که متناظر با ورودی گیت بعدی هستند. برای هر گیت، یک کلید متناظر با خروجی ۰ و یک کلید متناظر با خروجی ۱ داریم. اما چون چهار جعبه داریم، جعبههایی که همان خروجی را نمایش میدهند باید نسخههای تکراریِ همان کلید را در خود داشته باشند.
سیستمی که اینجا توصیف شد مدار گیجشدهِ Yao (Yao’s Garbled Circuit) نام دارد. توجه کنید که این تکنیک برای هر محاسبهای که بتوان آن را با یک مدار بولی نمایش داد قابل استفاده است. از آنجا که همه انواع محاسبات را میتوان به صورت مدارهای بولی بیان کرد، میتوانیم برای هر محاسبهای یک مدار گیجشده بسازیم. در سیستمهای رمزنگاری، جعبهها جای خود را به رمزنگاری میدهند و کلیدها نیز کلیدهای رمزنگاری خواهند بود. ما از همین رویکرد برای ساخت سیستم اثبات دانایی صفر خود استفاده خواهیم کرد.
اثبات دانایی صفر (Zero-knowledge Proof)
تا اینجا دیدیم که چطور میتوان از هر مدار، یک مدار گیجشده ساخت. حالا چطور میتوانیم از آن برای ساخت یک اثبات دانایی صفر استفاده کنیم؟
فرض کنید f تابعی است که مجموعهای از متغیرهای بولی را بهعنوان ورودی میگیرد و خروجی آن ۰ یا ۱ است. میتوانیم برای هر چیزی که میخواهیم اثبات کنیم چنین تابعی بیابیم. برای مثال، اگر اثباتگر ادعا کند که فاکتورگیری عدد n را میداند، تابع f(n, x) ما باید فقط و فقط در صورتی مقدار ۱ بدهد که ورودی x دو عدد بزرگتر از ۱ را نمایش دهد که حاصلضربشان برابر n است. میتوانیم این دو عدد را در نمایش دودویی بگیریم، یک مدار بولی برای محاسبه حاصلضرب آنها بسازیم و سپس مداری دیگر برای بررسی اینکه خروجی با نمایش دودویی n برابر است، تعریف کنیم.
اما اثباتگر چطور میتواند تاییدکننده را قانع کند که فاکتورگیری را میداند، بدون اینکه هیچ سرنخی درباره خود فاکتورگیری به تاییدکننده بدهد؟ تکنیک زیر را میتوانیم امتحان کنیم:
-
اثباتگر یک مدار گیجشده از مدار تابع f میسازد و آن را به تاییدکننده میدهد.
-
سپس اثباتگر کلیدهای متناظر با ورودی خودش x را در اختیار تاییدکننده قرار میدهد. توجه کنید که تاییدکننده نمیتواند تشخیص بدهد هر کلید متناظر ۰ است یا ۱.
-
اثباتگر همچنین با استفاده از همان ترفند پاکتها (envelope trick)، کلیدهای متناظر با ورودی تاییدکننده، یعنی n، را در اختیار او قرار میدهد. اما چون تاییدکننده لازم نیست n را پنهان کند، میتواند پاکتها را بهطور عمومی باز کند.
-
تاییدکننده مدار گیجشده را اجرا میکند و بررسی میکند که آیا خروجی نهایی ۱ است یا نه.
این تکنیک ورودی اثباتگر را از تاییدکننده پنهان میکند، اما تضمین نمیکند که اثباتگر تقلب نکرده باشد؛ مثلاً ممکن است مدار گیجشده تابعی متفاوت از f را پیادهسازی کند. برای اطمینان از اینکه مدار گیجشده بهدرستی ساخته شده است، تاییدکننده میخواهد اثباتگر همه جعبهها را برای همه گیتهای مدار و همچنین همه پاکتهای مربوط به کلیدهای ورودی باز کند. از سوی دیگر، اگر اثباتگر چنین کند، تاییدکننده بلافاصله ورودی اثباتگر را خواهد فهمید، چون خواهد دانست کدام ورودی اثباتگر با کدام کلید متناظر است.
راهحل به این صورت است:
-
اثباتگر دو نسخه از مدار گیجشده میسازد، هر کدام با مجموعهکلیدهای منحصربهفرد خودش.
-
اثباتگر هر دو نسخه را در دسترس عمومی قرار میدهد.
-
تاییدکننده بهطور تصادفی یکی از آنها را برای باز شدن توسط اثباتگر انتخاب میکند.
-
اثباتگر باید تمام جعبهها و تمام پاکتهای نسخه انتخابشده مدار را باز کند.
-
سپس تاییدکننده نسخه دیگر را با استفاده از کلیدهایی که اثباتگر داده اجرا میکند و بررسی میکند که آیا خروجی نهایی ۱ است یا نه.
(توجه کنید که تاییدکننده هیچ راز شخصی ندارد، بنابراین میتواند فرآیند تایید را بهطور عمومی انجام دهد و اثباتگر نیز میتواند مطمئن شود که اجرای مدار توسط تاییدکننده بهدرستی انجام شده است.)
از آنجا که هر کدام از نسخههای مدار با احتمال ۰٫۵ برای باز شدن انتخاب میشود، اگر اثباتگر دستکم یکی از مدارهای گیجشده را اشتباه ساخته باشد، با احتمال ۰٫۵ گیر خواهد افتاد و اعتبارش را از دست میدهد. اما اگر این تضمین کافی نباشد چه؟ اگر بخواهیم تقریباً مطمئن باشیم که اثباتگر متقلب حتماً گیر میافتد چه کار میکنیم؟
راه حل قویتر به این شکل است:
-
اثباتگر ۲۵۶ نسخه از مدار گیجشده میسازد، هر کدام با مجموعهکلیدهای منحصربهفرد.
-
اثباتگر همه آنها را در دسترس عمومی قرار میدهد.
-
تاییدکننده بهطور تصادفی ۱۲۸ نسخه را انتخاب میکند تا توسط اثباتگر باز شوند.
-
اثباتگر باید همه جعبهها و همه پاکتهای نسخههای انتخابشده را باز کند.
-
تاییدکننده تمام نسخههای باقیمانده را با استفاده از کلیدهایی که اثباتگر داده اجرا میکند و بررسی میکند که آیا همه آنها خروجی ۱ میدهند یا نه.
حالا اگر یکی از نسخههایی که توسط تاییدکننده اجرا میشود مدار درست تابع f باشد، اثباتگر مجبور است کلیدهای متناظر با «شاهد» صحیح (یعنی همان ورودی مخفی درست) را ارائه کند. در نتیجه اگر اثباتگر فاکتورگیری را نداند، باید حداقل ۱۲۸ نسخه را اشتباه بسازد تا شانسی برای قانع کردن تاییدکننده داشته باشد. اما در آن صورت، اثباتگر فقط زمانی گیر نمیافتد که تاییدکننده دقیقاً نسخههایی را برای باز شدن انتخاب کند که اشتباهاند و نسخههای درست را برای اجرا باقی بگذارد.
تعداد روشهایی که تاییدکننده میتواند ۱۲۸ نسخه را از بین ۲۵۶ نسخه انتخاب کند برابر است با:
(۲۵۶۱۲۸)\binom{256}{128}
فقط یکی از این انتخابها باعث میشود تاییدکننده قانع شود بدون اینکه اثباتگر متقلب گیر بیفتد. احتمال این حالت:
۱/(۲۵۶۱۲۸)<10−۷۵۱ / \binom{256}{128} < 10^{-75}
است. بنابراین اثباتگر متقلب تقریباً حتماً گیر خواهد افتاد. به این ترتیب یک سیستم اثبات دانایی صفر برای هر دانش محرمانهای که یک شرط مشخص را برآورده میکند، داریم.
فراتر از یک اثبات دانایی صفر
روش بالا راهی برای اثبات دانستن هر راز (Secret) که یک شرط مشخص را برآورده میکند، بهصورت دانایی صفر فراهم میکند. با این حال، این اثبات از نظر حجم ارتباط (Communication) و همچنین از نظر میزان محاسباتی که تاییدکننده باید انجام دهد، بسیار بزرگ و سنگین است. سیستمهای مدرن اثبات دانایی صفر به شما اجازه میدهند اثباتهایی بسیار کوتاه بسازید که میتوانند با مقدار بسیار کمی محاسبه تایید شوند.
این تکنیکهای مدرن نیازمند آشنایی با میدانهای متناهی (Finite Fields) هستند؛ یعنی مجموعههای متناهیای که جمع، تفریق، ضرب و تقسیم را روی عناصر خود بهصورت بسته و معتبر پشتیبانی میکنند. بنابراین در اینجا وارد آنها نمیشوم، اما خوانندگان علاقهمند میتوانند در منابع دیگر بیشتر در اینباره بیاموزند.
در این مقاله، یک روش ساده برای رسیدن به اثبات دانایی صفر برای یک مدار بولی عمومی معرفی کردیم. این روش به خواننده نشان میدهد که هر چیزی که بتوان آن را بدون دانایی صفر اثبات کرد، میتوان در قالب دانایی صفر هم اثبات کرد؛ چون هر تابعی را میتوان بهصورت یک مدار بولی نمایش داد و سپس مطابق روشی که در مقاله نشان دادیم، برای آن یک اثبات دانایی صفر ساخت.
البته این روش از نظر پیچیدگی ارتباطی بسیار گران است. در سامانههای عملی، به جای آن از اثباتهای دانایی صفر فشرده و مختصر، مانند SNARKها استفاده میشود.
