पेडरसन कमिटमेंट्स हमें किसी भी जानकारी को वैकल्पिक रूप से छिपाते हुए, एक सिंगल एलिप्टिक कर्व पॉइंट के साथ मनमाने ढंग से बड़े वेक्टर्स को एनकोड करने की अनुमति देते हैं।
यह हमें वेक्टर को प्रकट किए बिना उसके बारे में दावे (claims) करने की अनुमति देता है।
मोटिवेशन (Motivation)
जब हम Bulletproof Zero Knowledge Proofs पर चर्चा करते हैं, तो वे आमतौर पर “मेरे पास दो वेक्टर्स हैं जिनका इनर प्रोडक्ट है” के रूप में होंगे। यह बुनियादी लग सकता है, लेकिन वास्तव में आप इस तंत्र का उपयोग बहुत ही जटिल दावों को साबित करने के लिए कर सकते हैं। हम बाद में उस पर आएंगे।
लेकिन इस तरह के प्रूफ के काम करने के लिए, वेक्टर्स केवल प्रूवर के दिमाग में मौजूद नहीं हो सकते हैं - अन्यथा प्रूवर उन्हें अपनी इच्छानुसार बदल सकता है। उन्हें वास्तविक दुनिया में गणितीय संस्थाएं (entities) होना चाहिए। आम तौर पर, प्रूवर केवल दो वेक्टर्स को वेरिफायर को पास नहीं करना चाहता है, लेकिन फिर भी उन्हें वेरिफायर को यह दर्शाने के लिए “कुछ पास” करने की आवश्यकता होती है कि उन्होंने वेक्टर्स की एक जोड़ी चुनी है और इसे बदल नहीं सकते हैं।
यहीं पर पेडरसन कमिटमेंट्स तस्वीर में आते हैं।
एक इनर प्रोडक्ट आर्गुमेंट में, प्रूवर दो वेक्टर्स के लिए दो commitments प्रदान करता है, और फिर यह साबित करने के लिए प्रूफ देता है कि कमिट किए गए वेक्टर्स का एक निश्चित इनर प्रोडक्ट है।
पूर्वापेक्षाएँ (Prerequisites)
हम मानकर चलते हैं कि पाठक पहले से ही elliptic curve point addition और स्केलर मल्टीप्लिकेशन से परिचित है और किसी पॉइंट के “कर्व पर” होने का क्या अर्थ है, यह जानता है।
नोटेशन (Notation) के लिहाज से, बड़े अक्षर (capital letters) एलिप्टिक कर्व पॉइंट्स हैं, और छोटे अक्षर (lowercase letters) फाइनाइट फील्ड एलिमेंट्स हैं।
हम कहते हैं कि एक एलिप्टिक कर्व (EC) पॉइंट है, एक finite field एलिमेंट है, और , फाइनाइट फील्ड एलिमेंट और EC पॉइंट के बीच पॉइंट मल्टीप्लिकेशन है। व्यंजक एलिप्टिक कर्व पॉइंट एडिशन को दर्शाता है।
पारंपरिक कमिटमेंट्स (Traditional commitments)
जब हम स्मार्ट कॉन्ट्रैक्ट्स में कमिट रिवील (commit reveal) फंक्शंस डिज़ाइन करते हैं, तो वे आमतौर पर इस रूप में होते हैं
जहाँ एक रैंडम वैल्यू है ताकि किसी हमलावर (attacker) को ब्रूट-फोर्स (brute-force) तरीके से का अनुमान लगाने से रोका जा सके।
उदाहरण के लिए, यदि हम कोई वोट कमिट कर रहे थे, तो केवल सीमित संख्या में ही विकल्प होते हैं, और इस प्रकार सभी वोटों को आजमाकर और यह देखकर कि कौन सा हैश (hash) मेल खाता है, वोट चयन का अनुमान लगाया जा सकता है।
पेडरसन कमिटमेंट्स के मामले में salt वेरिएबल के लिए अकादमिक शब्दावली blinding factor है। क्योंकि यह रैंडम होता है, हमलावर को कमिट की गई वैल्यू का अनुमान लगाने में सक्षम होने से “अंधा” (blinded) कर दिया जाता है।
क्योंकि “commitment” वैल्यू का अनुमान किसी विरोधी (adversary) द्वारा नहीं लगाया जा सकता है, इसलिए हम कहते हैं कि यह कमिटमेंट स्कीम hiding है।
रिवील (reveal) चरण के दौरान, कमिटर (committer) वैल्यू और सॉल्ट को प्रकट करता है, ताकि दूसरी पार्टी (या स्मार्ट कॉन्ट्रैक्ट) यह मान्य कर सके कि यह मूल कमिटमेंट से मेल खाता है। एक और पेयर प्राप्त करना संभव नहीं है जो समान कमिटमेंट उत्पन्न कर सके, इसलिए हम कहते हैं कि यह स्कीम बाइंडिंग (binding) है - कमिटर अपनी कमिट की गई वैल्यू को बाद में बदल नहीं सकता (यानी उससे बंधा हुआ है)।
एक पेयर जो हैश उत्पन्न करता है, उसे opening कहा जाता है। यह कहने का अर्थ कि कोई “कमिटमेंट के लिए ओपनिंग जानता है”, यह है कि वे (value, salt) जानते हैं। को reveal करने का अर्थ है कमिटमेंट को open करना।
पेडरसन कमिटमेंट्स पर चर्चा करते समय, ओपनिंग को जानने (knowing) और कमिटमेंट को ओपन करने (opening) के बीच अंतर होता है। हम आमतौर पर यह साबित करना चाहते हैं कि हम ओपनिंग जानते हैं, लेकिन जरूरी नहीं कि हम इसे ओपन करें।
शब्दावली सारांश (Terminology summary)
- एक hiding कमिटमेंट किसी विरोधी को यह जानने की अनुमति नहीं देता है कि कमिटर द्वारा कौन सी वैल्यू चुनी गई थी। यह आमतौर पर एक रैंडम टर्म (term) शामिल करके पूरा किया जाता है जिसका हमलावर अनुमान नहीं लगा सकता है।
- एक blinding टर्म वह रैंडम नंबर है जो कमिटमेंट का अनुमान लगाना असंभव बना देता है।
- एक opening वे वैल्यूज़ हैं जो कमिटमेंट को कंप्यूट (compute) करेंगी।
- एक binding कमिटमेंट कमिटर को विभिन्न वैल्यूज़ के साथ हैश कंप्यूट करने की अनुमति नहीं देता है। अर्थात्, वे ऐसे दो (value, salt) पेयर नहीं खोज सकते जो समान वैल्यू पर हैश करते हों।
पेडरसन कमिटमेंट्स (Pedersen Commitments)
पेडरसन कमिटमेंट्स पहले वर्णित कमिट-रिवील स्कीम के समान ही व्यवहार करते हैं, सिवाय इसके कि वे क्रिप्टोग्राफिक हैश फंक्शंस के बजाय एलिप्टिक कर्व ग्रुप्स (elliptic curve groups) का उपयोग करते हैं।
डिस्क्रीट लॉगरिथम धारणा के तहत, दिए गए एलिप्टिक कर्व पॉइंट्स और के लिए, हम की गणना नहीं कर सकते जहाँ = हो। कहने का तात्पर्य यह है कि, हम उनके discrete log relationship को नहीं जानते हैं, यानी प्राप्त करने के लिए को अपने आप में कितनी बार जोड़ा जाना चाहिए।
हम अभी भी को के डिस्क्रीट लॉगरिथम के रूप में संदर्भित करते हैं, भले ही हम इसकी गणना नहीं कर सकते हैं, क्योंकि हम जानते हैं कि यह मौजूद है। सभी (क्रिप्टोग्राफिक) एलिप्टिक कर्व पॉइंट्स में एक डिस्क्रीट लॉगरिथम होता है, भले ही उनकी गणना न की जा सके।
इस अर्थ में, एलिप्टिक कर्व पॉइंट मल्टीप्लिकेशन एक हैश फंक्शन की तरह व्यवहार करता है। वे तब तक बाइंडिंग होते हैं जब तक हम केवल कर्व ऑर्डर (curve order) के भीतर ओपनिंग्स की अनुमति देते हैं।
हालाँकि, यदि डिस्क्रीट लॉगरिथम्स की सीमा (range) छोटी है और एप्लिकेशन के संदर्भ (जैसे वोट विकल्प) द्वारा बाध्य है, तो डिस्क्रीट लॉगरिथम का अनुमान लगाया जा सकता है।
हम पेडरसन कमिटमेंट को निम्नलिखित तरीके से हाइडिंग (hiding) बना सकते हैं:
जहाँ वह वैल्यू है जिसे हम कमिट कर रहे हैं और सॉल्ट (या ब्लाइंडिंग फैक्टर) है और एक अन्य एलिप्टिक कर्व पॉइंट है जिससे कमिटर और के बीच के डिस्क्रीट लॉगरिथम संबंध को नहीं जानता है।
हमें इस बात पर जोर देना चाहिए कि यद्यपि डिस्क्रीट लॉगरिथम्स अज्ञात हैं, पॉइंट्स और सार्वजनिक हैं और वेरिफायर और कमिटर दोनों को ज्ञात हैं।
कमिटर को और के बीच डिस्क्रीट लॉगरिथम संबंध क्यों नहीं जानना चाहिए
मान लीजिए कि कमिटर को जानता है जिससे है।
उस स्थिति में, वे कमिटमेंट
को मूल रूप से कमिट की गई वैल्यू के अलावा एक अलग पर ओपन कर सकते हैं।
यहाँ बताया गया है कि कमिटर कैसे धोखा दे सकता है यदि वे जानते हैं कि , का डिस्क्रीट लॉगरिथम है।
कमिटर कमिटमेंट समीकरण को फिर से लिख सकता है:
कमिटर एक नई वैल्यू चुनता है और की गणना करता है:
फिर, प्रूवर जाली (forged) ओपनिंग के रूप में प्रस्तुत करता है।
यह काम करता है क्योंकि
इसलिए, कमिटर को उनके द्वारा उपयोग किए जा रहे एलिप्टिक कर्व पॉइंट्स के बीच डिस्क्रीट लॉगरिथम संबंध नहीं जानना चाहिए।
इसे पूरा करने का एक तरीका यह है कि एक वेरिफायर कमिटर के लिए एलिप्टिक कर्व पॉइंट्स की आपूर्ति करे। हालाँकि, एक सरल तरीका यह है कि एलिप्टिक कर्व पॉइंट्स को रैंडम और पारदर्शी तरीके से चुना जाए, जैसे कि एलिप्टिक कर्व पॉइंट्स को स्यूडोरैंडमली (pseudorandomly) चुनकर। एक रैंडम एलिप्टिक कर्व पॉइंट को देखते हुए, हम उसका डिस्क्रीट लॉगरिथम नहीं जानते हैं।
उदाहरण के लिए, हम जनरेटर (generator) पॉइंट से शुरू कर सकते हैं, और वैल्यूज़ को हैश कर सकते हैं, फिर अगले पॉइंट के लिए स्यूडोरैंडम लेकिन नियतात्मक (deterministic) खोज को सीड (seed) करने के लिए उसका उपयोग कर सकते हैं।
पेडरसन कमिटमेंट्स उपयोगी क्यों हैं?
ऐसा लगता है कि पेडरसन कमिटमेंट्स केवल एक अलग हैश-फंक्शन के साथ एक सामान्य कमिट-रिवील हैं, तो इसका क्या फायदा है?
इस स्कीम के कुछ फायदे हैं।
पेडरसन कमिटमेंट्स एडिटिवली होमोमोर्फिक (additively homomorphic) होते हैं
एक पॉइंट दिए जाने पर, हम दो कमिटमेंट्स को एक साथ जोड़ सकते हैं = ।
यदि हम रैंडम ब्लाइंडिंग टर्म्स शामिल करते हैं, तो हम अभी भी ब्लाइंडिंग टर्म्स को एक साथ जोड़कर और उसे वेरिफायर को प्रदान करके एक वैध ओपनिंग कर सकते हैं। मान लीजिए कि और कमिटमेंट्स हैं। अब विचार करें कि जब हम को एक साथ जोड़ते हैं तो क्या होता है:
वैकल्पिक रूप से, वेरिफायर यह जाँच कर सकता है कि
नियमित हैश (जैसे SHA-256) को इस तरह से एक साथ नहीं जोड़ा जा सकता है।
दो पेडरसन कमिटमेंट्स दिए गए हैं जो कमिट करने के लिए समान एलिप्टिक कर्व पॉइंट्स का उपयोग करते हैं, हम कमिटमेंट्स को एक साथ जोड़ सकते हैं और फिर भी उनके लिए एक वैध ओपनिंग रख सकते हैं।
पेडरसन कमिटमेंट्स प्रूवर को कमिट की गई वैल्यूज़ के योग (sums) के बारे में दावे करने की अनुमति देते हैं।
हम एक ही पॉइंट में जितने चाहें उतने पॉइंट्स को एनकोड कर सकते हैं
और के उपयोग के हमारे उदाहरण को बिना ब्लाइंडिंग टर्म के 2D वेक्टर कमिटमेंट के रूप में भी सोचा जा सकता है। लेकिन हम जितने चाहें उतने एलिप्टिक कर्व पॉइंट्स जोड़ सकते हैं और जितने चाहें उतने स्केलर्स को कमिट कर सकते हैं। (यहाँ, , , आदि का अर्थ एक ही समूह में अलग-अलग पॉइंट हैं, अलग-अलग समूहों के जनरेटर नहीं)।
पेडरसन वेक्टर कमिटमेंट्स (Pedersen Vector Commitments)
हम उपरोक्त स्कीम को एक कदम आगे ले जा सकते हैं और केवल एक वैल्यू और एक ब्लाइंडिंग टर्म के बजाय वैल्यूज़ के एक सेट को कमिट कर सकते हैं।
वेक्टर कमिटमेंट स्कीम (Vector commitment scheme)
मान लीजिए कि हमारे पास रैंडम एलिप्टिक कर्व पॉइंट्स का एक सेट है (जिनका डिस्क्रीट लॉगरिथम हम नहीं जानते हैं), और हम निम्नलिखित कार्य करते हैं:
यह हमें के लिए वैल्यूज़ को कमिट करने और इसे के साथ छिपाने की सुविधा देता है।
चूँकि कमिटर किसी भी का डिस्क्रीट लॉगरिथम नहीं जानता है, वे का डिस्क्रीट लॉगरिथम नहीं जानते हैं। इसलिए, यह स्कीम बाइंडिंग है: वे बाद में उत्पन्न करने के लिए केवल को प्रकट कर सकते हैं, वे कोई अन्य वेक्टर उत्पन्न नहीं कर सकते।
वेक्टर कमिटमेंट्स को कंबाइन किया जा सकता है
हम दो वेक्टर्स के लिए एक कमिटमेंट प्राप्त करने के लिए दो पेडरसन वेक्टर कमिटमेंट्स जोड़ सकते हैं। यह अभी भी कमिटर को केवल मूल वेक्टर्स को ओपन करने की अनुमति देगा। महत्वपूर्ण कार्यान्वयन (implementation) विवरण यह है कि हमें कमिट करने के लिए एलिप्टिक कर्व पॉइंट्स के एक अलग सेट का उपयोग करना होगा।
और को एक साथ जोड़कर, हम कार्यात्मक रूप से आकार का एक बड़ा वेक्टर कमिट कर रहे हैं।
यहाँ, और ब्लाइंडिंग टर्म्स हैं। भले ही कमिटर शून्य वेक्टर (zero vector) को कमिट करता है, कमिटमेंट अभी भी एक रैंडम पॉइंट प्रतीत होगा।
कमिटर बाद में मूल वेक्टर्स और तथा ब्लाइंडिंग टर्म को प्रकट करेगा। यह बाइंडिंग है: वे वेक्टर्स और ब्लाइंडिंग टर्म्स की कोई अन्य जोड़ी प्रकट नहीं कर सकते हैं।
यह तथ्य कि हम एक वेक्टर के लिए और दूसरे के लिए का उपयोग कर रहे हैं, इसका यह अर्थ नहीं होना चाहिए कि पॉइंट्स के बीच एक विशेष संबंध है और पॉइंट्स के बीच एक विशेष संबंध है। सभी पॉइंट्स को स्यूडोरैंडमली चुना जाना चाहिए। यह केवल यह कहने के लिए एक नोटेशनल (notational) सुविधा है कि “एलिप्टिक कर्व पॉइंट्स का यह वेक्टर, फील्ड एलिमेंट्स के इस वेक्टर के साथ जाता है, और EC पॉइंट्स का यह अन्य वेक्टर, फील्ड एलिमेंट्स के इस अन्य वेक्टर के साथ जाता है।”
हम जितने वेक्टर्स को कमिट कर सकते हैं, उसकी कोई व्यावहारिक ऊपरी सीमा (upper limit) नहीं है।
पाठकों के लिए अभ्यास: यदि हमने उन्हें जोड़ने से पहले दोनों वेक्टर्स के लिए समान का उपयोग किया, तो कमिटर के लिए दो अलग-अलग वेक्टर्स कैसे ओपन कर सकता है? एक उदाहरण दें। पॉइंट्स के एक अलग सेट का उपयोग इसे कैसे रोकता है?
पाठकों के लिए अभ्यास: यदि कमिटर वेक्टर के अंदर समान एलिमेंट्स को स्विच करने का प्रयास करता है तो क्या होता है?
उदाहरण के लिए, वे कमिट करते हैं:
लेकिन पहले दो एलिमेंट्स की अदला-बदली (swapped) के साथ ओपन करते हैं:
अर्थात्, वे बाकी सब कुछ अपरिवर्तित छोड़ते हुए पहले दो एलिमेंट्स को स्विच करते हैं। मान लें कि वेक्टर अनपरम्यूटेड (unpermuted) है।
पारदर्शी तरीके से रैंडम पॉइंट्स उत्पन्न करना
हम ये रैंडम एलिप्टिक कर्व पॉइंट्स कैसे उत्पन्न कर सकते हैं? एक स्पष्ट समाधान ट्रेंस्टेड सेटअप (trusted setup) का उपयोग करना है, लेकिन यह आवश्यक नहीं है। कमिटर पारदर्शी तरीके से पॉइंट्स को रैंडमली चुनकर पॉइंट्स को इस तरह से सेटअप करने में सक्षम है कि वे अपना डिस्क्रीट लॉगरिथम नहीं जान सकते।
वे जनरेटर पॉइंट चुन सकते हैं, सार्वजनिक रूप से चुने गए रैंडम नंबर में मिला सकते हैं, और एक अन्य वैल्यू प्राप्त करने के लिए उस परिणाम को हैश कर सकते हैं (और इसे फील्ड मॉड्यूलर के मॉड्यूलो में ले सकते हैं)। यदि इसका परिणाम -वैल्यू में होता है जो एलिप्टिक कर्व पर स्थित है, तो उसे अगले जनरेटर के रूप में उपयोग करें और पेयर को फिर से हैश करें। अन्यथा, यदि -वैल्यू कर्व पर नहीं आती है, तो को तब तक बढ़ाएं (increment) जब तक कि ऐसा न हो जाए। चूँकि कमिटर पॉइंट्स उत्पन्न नहीं कर रहा है, वे उनके डिस्क्रीट लॉग को नहीं जानते हैं।
अभ्यास: अज्ञात डिस्क्रीट लॉग्स के साथ n पॉइंट्स उत्पन्न करने के लिए निम्नलिखित कोड को एडजस्ट करें:
from py_ecc.bn128 import is_on_curve, FQ
from py_ecc.fields import field_properties
field_mod = field_properties["bn128"]["field_modulus"]
from hashlib import sha256
from libnum import has_sqrtmod_prime_power, sqrtmod_prime_power
b = 3 # for bn128, y^2 = x^3 + 3
seed = "RareSkills"
x = int(sha256(seed.encode('ascii')).hexdigest(), 16) % field_mod
entropy = 0
vector_basis = []
# modify the code below to generate n points
while not has_sqrtmod_prime_power((x**3 + b) % field_mod, field_mod, 1):
# increment x, so hopefully we are on the curve
x = (x + 1) % field_mod
entropy = entropy + 1
# pick the upper or lower point depending on if entropy is even or odd
y = list(sqrtmod_prime_power((x**3 + b) % field_mod, field_mod, 1))[entropy & 1 == 0]
point = (FQ(x), FQ(y))
assert is_on_curve(point, b), "sanity check"
vector_basis.append(point)
# new x value
x = int(sha256(str(x).encode('ascii')).hexdigest(), 16) % field_mod
print(vector_basis)
किसी भी बिंदु पर आपको एक स्केलर (scalar) चुनकर और फिर उसे जनरेटर से गुणा करके पॉइंट उत्पन्न नहीं करना चाहिए, क्योंकि इससे डिस्क्रीट लॉगरिथम ज्ञात हो जाएगा। आपको हैश फ़ंक्शन के माध्यम से कर्व पॉइंट के वैल्यूज़ को स्यूडोरैंडमली चुनना होगा और यह पता लगाना होगा कि क्या यह कर्व पर है।
जनरेटर (जिसका ज्ञात डिस्क्रीट लॉगरिथम 1 है) के साथ शुरुआत करना और अन्य पॉइंट्स उत्पन्न करना ठीक है।
पाठकों के लिए अभ्यास: मान लीजिए कि हम पॉइंट्स और के लिए वैल्यूज़ का एक वेक्टर कमिट करते हैं। का डिस्क्रीट लॉगरिथम ज्ञात है, लेकिन का डिस्क्रीट लॉगरिथम ज्ञात नहीं है। हम अभी के लिए ब्लाइंडिंग टर्म को अनदेखा कर देंगे। क्या कमिटर दो अलग-अलग वेक्टर्स को ओपन कर सकता है? क्यों या क्यों नहीं?
RareSkills के साथ और जानें
यदि आप learn zero knowledge proofs चाहते हैं तो हमारे ZK बूटकैंप को देखें।