Rank 1 Constraint System के रूप में एन्कोड किए गए arithmetic circuit को देखते हुए, witness होने का एक ZK-proof बनाना संभव है, भले ही यह संक्षिप्त (succinct) न हो। यह लेख वर्णन करता है कि इसे कैसे पूरा किया जाए।
R1CS के लिए एक zero knowledge proof, witness vector को finite field elliptic curve points में परिवर्तित करके और प्रत्येक पंक्ति (row) के लिए Hadamard product को bilinear pairing से बदलकर पूरा किया जाता है।
एक Rank 1 Constraint System को देखते हुए जहाँ प्रत्येक मैट्रिक्स में n पंक्तियाँ (rows) और m कॉलम (columns) हैं, हम इसे इस प्रकार लिखते हैं:
La∘Ra=Oa
जहाँ L, R, O ऐसे मैट्रिक्स हैं जिनमें n पंक्तियाँ और m कॉलम हैं, और a witness vector है (जिसमें arithmetic circuit के प्रत्येक सिग्नल के लिए एक satisfying assignment होता है)। वेक्टर a में 1 कॉलम और m पंक्तियाँ हैं और ∘ element-wise multiplication (Hadamard product) है।
इस सेटअप में, हम एक verifier को साबित कर सकते हैं कि हमारे पास एक witness vector a है जो R1CS को संतुष्ट करता है, बस उन्हें वेक्टर a देकर। लेकिन इसमें स्पष्ट खामी यह है कि यह एक zero knowledge proof नहीं है!
R1CS के लिए Zero knowledge proof एल्गोरिदम
यदि हम witness vector की प्रत्येक प्रविष्टि (entry) को G1 या G2 से गुणा करके “एन्क्रिप्ट (encrypt)” करते हैं, तो भी गणित ठीक से काम करेगा!
इसे समझने के लिए, मान लें कि यदि हम यह मैट्रिक्स गुणा करते हैं:
[1324][45]=[1432]
और साथ ही:
[1324][4G15G1]=[14G132G1]
दूसरे मैट्रिक्स गुणा में दो elliptic curve points के discrete logs का मान वही है जो पहले मैट्रिक्स गुणा के तत्वों (elements) का है।
दूसरे शब्दों में, हर बार जब हम कॉलम वेक्टर को स्क्वायर मैट्रिक्स की एक पंक्ति से गुणा करते हैं, तो हम दो elliptic curve point multiplications और एक elliptic curve addition करते हैं।
Elliptic curves के लिए नोटेशन (Notation)
हम कहते हैं कि [aG1]1 एक G1 elliptic curve point है जो फ़ील्ड एलिमेंट a को G1 से गुणा करके बनाया गया है। हम कहते हैं कि [aG2]2 एक G2 elliptic curve point है जो a को जनरेटर G2 से गुणा करके उत्पन्न किया गया है। Discrete log problem के कारण, हम [aG1]1 या [aG2]2 दिए जाने पर a नहीं निकाल सकते। A∈G1 और B∈G2 point दिए जाने पर, हम कहते हैं कि दो points की pairing A∙B है।
Prover के कदम (Steps)
आइए अपने a वेक्टर को एन्क्रिप्ट करें, जिसके लिए प्रत्येक प्रविष्टि को जनरेटर पॉइंट G1 से गुणा करके elliptic curve point [aiG1]1 तैयार किया जाएगा।
मैट्रिक्स L के लिए, हम निम्नलिखित कार्य कर रहे हैं:
Hadamard product के elliptic curve pairings की सूची बनने के अनुमान में, हम a वेक्टर को एन्क्रिप्ट करने के लिए G2 points का भी उपयोग कर सकते हैं ताकि verifier pairing कर सके।
इस ऑपरेशन के बाद, हमारे पास G1 में elliptic curve points का एक सिंगल कॉलम है जो La के गुणा से उत्पन्न हुआ है और Ra से G2 points का एक सिंगल कॉलम है।
इसका सरल (naive) अगला कदम a वेक्टर को G12 points के साथ एन्क्रिप्ट करना होगा ताकि verifier La के परिणाम को Ra के साथ pair कर सके यह देखने के लिए कि क्या यह Oa के बराबर है। लेकिन G12 points बहुत बड़े होते हैं, इसलिए हम चाहेंगे कि verifier G1 में Oa elliptic curve points को pair करे और फिर प्रत्येक प्रविष्टि को G2 point के साथ pair करे। G2 point के साथ pairing करना, एक तरह से “एक से गुणा करना” है लेकिन यह G1 point को G12 point में बदल देता है।
Prover फिर G1 वेक्टर और G2 वेक्टर verifier को सौंप देता है।
G12 तत्वों (elements) के उपरोक्त वेक्टर तभी और केवल तभी element-wise बराबर होंगे जब prover ने एक वैध (valid) witness प्रदान किया हो।
खैर, लगभग। हम अगले अनुभाग में उस पर चर्चा करेंगे।
सबसे पहले हमें एक महत्वपूर्ण इम्प्लीमेंटेशन विवरण का उल्लेख करने की आवश्यकता है:
Public inputs
यदि हमारा नॉलेज क्लेम “मुझे x पता है ताकि x3+5x+5=y जहाँ y=155” है, तो हमारा witness vector संभवतः निम्नलिखित जैसा दिखेगा:
[1,y,x,v]
जहाँ v=x2 है। इस स्थिति में, हमें [1,y] को पब्लिक (public) करने की आवश्यकता है। इसे पूरा करने के लिए, हम बस witness के पहले दो तत्वों को एन्क्रिप्ट नहीं करते हैं। Verifier पब्लिक आउटपुट्स की जाँच करेगा, फिर पब्लिक इनपुट्स को G1 या G2 पॉइंट से गुणा करके एन्क्रिप्ट करेगा ताकि verification फॉर्मूला न बदले।
एक दुर्भावनापूर्ण (malicious) prover से निपटना।
चूँकि वेक्टर एन्क्रिप्टेड होते हैं, verifier तुरंत यह नहीं जान सकता कि क्या G1 points का वेक्टर उन्हीं मानों (values) को एन्क्रिप्ट करता है जिन्हें G2 points का वेक्टर करता है।
अर्थात, prover aG1 और aG2 प्रदान कर रहा है। चूँकि verifier को points के वेक्टर के discrete logs नहीं पता हैं, तो verifier को कैसे पता चलेगा कि G1 points के वेक्टर के discrete logs वही हैं जो G2 points के वेक्टर के हैं?
Verifier (उन्हें जाने बिना) discrete logs की समानता की जाँच कर सकता है, जिसके लिए वह points के दोनों वेक्टर्स को विपरीत (opposite) जनरेटर के वेक्टर के साथ pair करता है और यह देखता है कि परिणामी G12 points बराबर हैं या नहीं। विशेष रूप से:
यह एल्गोरिदम verifier के लिए बहुत अक्षम (inefficient) है। यदि R1CS में मैट्रिक्स बड़े हैं (और दिलचस्प एल्गोरिदम के लिए, वे होंगे), तो verifier को बहुत सारी pairings और elliptic curve additions करने होंगे। Elliptic curve addition काफी तेज़ है, लेकिन elliptic curve pairings धीमी हैं (और Ethereum पर बहुत अधिक गैस खर्च होती है)।
हालाँकि, यह देखना अच्छा है कि इस स्तर पर, zero knowledge proofs संभव हैं, और यदि आपको elliptic curve operations की अच्छी समझ है (और आप अपना मैट्रिक्स अंकगणित नहीं भूले हैं), तो उन्हें समझना मुश्किल नहीं है।
इस तकनीक को पूरी तरह से zero knowledge बनाना
जैसा कि यह अभी है, हमारे witness vector को डिक्रिप्ट (decrypt) नहीं किया जा सकता है, हालाँकि इसका अनुमान लगाया जा सकता है। यदि कोई हमलावर (कोई व्यक्ति जो अनएन्क्रिप्टेड witness को खोजने की कोशिश कर रहा है) witness का एक शिक्षित अनुमान (educated guess) लगाने के लिए कुछ सहायक (auxiliary) जानकारी का उपयोग करता है, तो वे अपने अनुमानित witness vector को elliptic curve point generators से गुणा करके और यह देखकर कि क्या परिणाम prover के witness vectors के समान है, अपने काम की जाँच कर सकते हैं।
हम Groth16 के अपने कवरेज में witness का अनुमान लगाने से बचाव करना सीखेंगे।
इसके अलावा, ध्यान रखें कि वास्तविक दुनिया में कोई भी वर्णित एल्गोरिदम नहीं करता है, क्योंकि यह बहुत अक्षम है। हालाँकि, यदि आप इसे लागू (implement) करते हैं, तो यह आपको सार्थक elliptic curve arithmetic को लागू करने का अभ्यास करने और एक कार्यात्मक एंड-टू-एंड (लगभग) zero knowledge proof बनाने में मदद करेगा।
आप Obront द्वारा वर्णित एल्गोरिदम का एक उदाहरण इम्प्लीमेंटेशन इस रेपो (repo) में देख सकते हैं।