प्रमुख मजकुराकडे जा

गुप्त पत्त्यांचा वापर

गुप्त पत्ता
गोपनीयता
कूटलेखन
Rust
wasm
मध्यम
Ori Pomerantz
३० नोव्हेंबर, २०२५
15 मिनिट वाचन

तुम्ही बिल आहात. ज्या कारणांमध्ये आपण जाणार नाही, त्या कारणास्तव, तुम्हाला "Alice for Queen of the World" मोहिमेसाठी देणगी द्यायची आहे आणि तुम्ही देणगी दिली आहे हे ॲलिसला कळावे असे तुम्हाला वाटते, जेणेकरून ती जिंकल्यास तुम्हाला बक्षीस देईल. दुर्दैवाने, तिचा विजय निश्चित नाही. एक प्रतिस्पर्धी मोहीम आहे, "Carol for Empress of the Solar System". जर कॅरोल जिंकली आणि तिला कळले की तुम्ही ॲलिसला देणगी दिली आहे, तर तुम्ही अडचणीत याल. म्हणून तुम्ही तुमच्या खात्यातून ॲलिसच्या खात्यात फक्त 200 ETH हस्तांतरित करू शकत नाही.

ERC-5564 (opens in a new tab) मध्ये याचे समाधान आहे. हे ERC अज्ञात हस्तांतरणासाठी गुप्त पत्त्यांचा (opens in a new tab) वापर कसा करायचा हे स्पष्ट करते.

चेतावणी: गुप्त पत्त्यांमागील कूटलेखन, आमच्या माहितीनुसार, सुरक्षित आहे. तथापि, संभाव्य साइड-चॅनल हल्ले होऊ शकतात. खाली, हा धोका कमी करण्यासाठी तुम्ही काय करू शकता ते तुम्हाला दिसेल.

गुप्त पत्ते कसे कार्य करतात

हा लेख गुप्त पत्ते दोन प्रकारे स्पष्ट करण्याचा प्रयत्न करेल. पहिले म्हणजे त्यांचा वापर कसा करायचा. लेखाचा उर्वरित भाग समजून घेण्यासाठी हा भाग पुरेसा आहे. त्यानंतर, त्यामागील गणिताचे स्पष्टीकरण आहे. जर तुम्हाला कूटलेखनात रस असेल, तर हा भाग देखील वाचा.

साधी आवृत्ती (गुप्त पत्त्यांचा वापर कसा करायचा)

ॲलिस दोन खाजगी की तयार करते आणि संबंधित सार्वजनिक की प्रकाशित करते (ज्या एकाच दुप्पट-लांबीच्या मेटा-पत्त्यामध्ये एकत्र केल्या जाऊ शकतात). बिल देखील एक खाजगी की तयार करतो आणि संबंधित सार्वजनिक की प्रकाशित करतो.

एका पक्षाची सार्वजनिक की आणि दुसऱ्याची खाजगी की वापरून, तुम्ही एक सामायिक गुप्त (shared secret) मिळवू शकता जे केवळ ॲलिस आणि बिल यांनाच माहीत आहे (ते केवळ सार्वजनिक कीमधून मिळवता येत नाही). हे सामायिक गुप्त वापरून, बिलला गुप्त पत्ता मिळतो आणि तो त्यावर मालमत्ता पाठवू शकतो.

ॲलिसला सामायिक गुप्तानंतर पत्ता मिळतो, परंतु तिने प्रकाशित केलेल्या सार्वजनिक कींच्या खाजगी की तिला माहीत असल्यामुळे, तिला त्या पत्त्यावरून पैसे काढण्यासाठी खाजगी की देखील मिळू शकते.

गणित (गुप्त पत्ते असे का कार्य करतात)

मानक गुप्त पत्ते एलिप्टिक-कर्व्ह क्रिप्टोग्राफी (ECC) (opens in a new tab) वापरतात ज्यामुळे कमी की बिट्ससह चांगली कामगिरी मिळते, आणि त्याच वेळी सुरक्षेची पातळी कायम राहते. परंतु बहुतेक वेळा आपण त्याकडे दुर्लक्ष करू शकतो आणि आपण नियमित अंकगणित वापरत आहोत असे भासवू शकतो.

एक संख्या आहे जी प्रत्येकाला माहीत आहे, G. तुम्ही G ने गुणू शकता. परंतु ECC च्या स्वरूपामुळे, G ने भागणे व्यावहारिकदृष्ट्या अशक्य आहे. Ethereum मध्ये सार्वजनिक की कूटलेखन सामान्यतः ज्या प्रकारे कार्य करते ते म्हणजे, तुम्ही व्यवहार स्वाक्षरी करण्यासाठी एक खाजगी की, Ppriv वापरू शकता, जे नंतर सार्वजनिक की, Ppub = GPpriv द्वारे सत्यापित केले जातात.

ॲलिस दोन खाजगी की तयार करते, Kpriv आणि Vpriv. Kpriv चा वापर गुप्त पत्त्यामधून पैसे खर्च करण्यासाठी केला जाईल, आणि Vpriv चा वापर ॲलिसच्या मालकीचे पत्ते पाहण्यासाठी केला जाईल. त्यानंतर ॲलिस सार्वजनिक की प्रकाशित करते: Kpub = GKpriv आणि Vpub = GVpriv

बिल तिसरी खाजगी की, Rpriv तयार करतो, आणि Rpub = GRpriv एका केंद्रीय नोंदणीमध्ये प्रकाशित करतो (बिलने ते ॲलिसला देखील पाठवले असते, परंतु आम्ही असे गृहीत धरतो की कॅरोल ऐकत आहे).

बिल RprivVpub = GRprivVpriv ची गणना करतो, जे ॲलिसला देखील माहीत असेल अशी त्याला अपेक्षा आहे (खाली स्पष्ट केले आहे). या मूल्याला S, म्हणजेच सामायिक गुप्त (shared secret) म्हणतात. यामुळे बिलला एक सार्वजनिक की मिळते, Ppub = Kpub+G*hash(S). या सार्वजनिक कीमधून, तो एक पत्ता मोजू शकतो आणि त्याला हवी असलेली कोणतीही संसाधने त्यावर पाठवू शकतो. भविष्यात, जर ॲलिस जिंकली, तर बिल तिला Rpriv सांगून संसाधने त्याच्याकडून आली आहेत हे सिद्ध करू शकतो.

ॲलिस RpubVpriv = GRprivVpriv ची गणना करते. यामुळे तिला तेच सामायिक गुप्त, S मिळते. तिला खाजगी की, Kpriv माहीत असल्यामुळे, ती Ppriv = Kpriv+hash(S) ची गणना करू शकते. ही की तिला Ppub = GPpriv = GKpriv+G*hash(S) = Kpub+G*hash(S) मधून मिळणाऱ्या पत्त्यातील मालमत्तांमध्ये प्रवेश करू देते.

आमच्याकडे एक वेगळी व्ह्यूइंग की (viewing key) आहे, जी ॲलिसला डेव्हच्या वर्ल्ड डॉमिनेशन कॅम्पेन सर्व्हिसेसला उपकंत्राट देण्यास अनुमती देते. ॲलिस डेव्हला सार्वजनिक पत्ते कळवण्यास आणि अधिक पैसे उपलब्ध झाल्यावर तिला माहिती देण्यास तयार आहे, परंतु तिने तिच्या मोहिमेचे पैसे खर्च करावेत असे तिला वाटत नाही.

पाहणे आणि खर्च करणे यासाठी स्वतंत्र की वापरल्या जातात, त्यामुळे ॲलिस डेव्हला Vpriv देऊ शकते. त्यानंतर डेव्ह S = RpubVpriv = GRprivVpriv ची गणना करू शकतो आणि त्याद्वारे सार्वजनिक की (Ppub = Kpub+G*hash(S)) मिळवू शकतो. परंतु Kpriv शिवाय डेव्ह खाजगी की मिळवू शकत नाही.

सारांश, ही मूल्ये विविध सहभागींना ज्ञात आहेत.

ॲलिसप्रकाशितबिलडेव्ह
GGGG
Kpriv---
Vpriv--Vpriv
Kpub = GKprivKpubKpubKpub
Vpub = GVprivVpubVpubVpub
--Rpriv-
RpubRpubRpub = GRprivRpub
S = RpubVpriv = GRprivVpriv-S = RprivVpub = GRprivVprivS = RpubVpriv = GRprivVpriv
Ppub = Kpub+G*hash(S)-Ppub = Kpub+G*hash(S)Ppub = Kpub+G*hash(S)
पत्ता=f(Ppub)-पत्ता=f(Ppub)पत्ता=f(Ppub)पत्ता=f(Ppub)
Ppriv = Kpriv+hash(S)---

जेव्हा गुप्त पत्ते चुकीचे ठरतात

ब्लॉकचेनवर कोणतीही रहस्ये नसतात. जरी गुप्त पत्ते तुम्हाला गोपनीयता देऊ शकतात, तरीही ती गोपनीयता ट्रॅफिक विश्लेषणासाठी असुरक्षित असते. एक सोपे उदाहरण घ्यायचे झाल्यास, कल्पना करा की बिल एका पत्त्याला निधी देतो आणि लगेच Rpub मूल्य प्रकाशित करण्यासाठी एक व्यवहार पाठवतो. ॲलिसच्या Vpriv शिवाय, हा एक गुप्त पत्ता आहे याची खात्री आपण करू शकत नाही, परंतु तसा अंदाज लावता येतो. त्यानंतर, आम्हाला आणखी एक व्यवहार दिसतो जो त्या पत्त्यावरून सर्व ETH ॲलिसच्या मोहीम निधी पत्त्यावर हस्तांतरित करतो. आम्ही ते सिद्ध करू शकत नाही, परंतु बहुधा बिलने नुकतीच ॲलिसच्या मोहिमेला देणगी दिली आहे. कॅरोलला नक्कीच असे वाटेल.

बिलसाठी Rpub चे प्रकाशन आणि गुप्त पत्त्यासाठी निधी देणे हे वेगळे करणे सोपे आहे (हे वेगवेगळ्या वेळी, वेगवेगळ्या पत्त्यांवरून करा). तथापि, ते पुरेसे नाही. कॅरोल जो पॅटर्न शोधते तो असा आहे की बिल एका पत्त्याला निधी देतो, आणि नंतर ॲलिसचा मोहीम निधी त्यातून पैसे काढतो.

एक उपाय म्हणजे ॲलिसच्या मोहिमेने थेट पैसे काढू नये, तर ते तिसऱ्या पक्षाला पैसे देण्यासाठी वापरावे. जर ॲलिसची मोहीम डेव्हच्या वर्ल्ड डॉमिनेशन कॅम्पेन सर्व्हिसेसला 10 ETH पाठवते, तर कॅरोलला फक्त एवढेच कळते की बिलने डेव्हच्या एका ग्राहकाला देणगी दिली आहे. जर डेव्हकडे पुरेसे ग्राहक असतील, तर कॅरोलला हे कळू शकणार नाही की बिलने तिच्याशी स्पर्धा करणाऱ्या ॲलिसला देणगी दिली की ॲडम, अल्बर्ट किंवा ॲबिगेल यांना, ज्यांची कॅरोलला पर्वा नाही. ॲलिस पेमेंटसोबत एक हॅश केलेले मूल्य समाविष्ट करू शकते, आणि नंतर डेव्हला प्रीइमेज देऊ शकते, हे सिद्ध करण्यासाठी की ती तिची देणगी होती. वैकल्पिकरित्या, वर नमूद केल्याप्रमाणे, जर ॲलिसने डेव्हला तिची Vpriv दिली, तर त्याला आधीच कळते की पेमेंट कोणाकडून आले आहे.

या उपायातील मुख्य समस्या अशी आहे की, जेव्हा ती गुप्तता बिलच्या फायद्याची असते तेव्हा ॲलिसने गुप्ततेची काळजी घेणे आवश्यक असते. ॲलिसला तिची प्रतिष्ठा टिकवून ठेवायची असेल, जेणेकरून बिलचा मित्र बॉब देखील तिला देणगी देईल. परंतु हे देखील शक्य आहे की तिला बिलला उघड करण्यास हरकत नसेल, कारण मग कॅरोल जिंकल्यास काय होईल याची त्याला भीती वाटेल. बिल कदाचित ॲलिसला आणखी जास्त पाठिंबा देऊ शकेल.

अनेक गुप्त स्तरांचा वापर करणे

बिलची गोपनीयता जपण्यासाठी ॲलिसवर अवलंबून राहण्याऐवजी, बिल ते स्वतः करू शकतो. तो बॉब आणि बेला या काल्पनिक लोकांसाठी अनेक मेटा-पत्ते तयार करू शकतो. बिल नंतर बॉबला ETH पाठवतो, आणि "बॉब" (जो खरं तर बिल आहे) ते बेलाला पाठवतो. "बेला" (जो बिलच आहे) ते ॲलिसला पाठवते.

कॅरोल तरीही ट्रॅफिक विश्लेषण करू शकते आणि बिल-ते-बॉब-ते-बेला-ते-ॲलिस पाइपलाइन पाहू शकते. तथापि, जर "बॉब" आणि "बेला" देखील इतर कारणांसाठी ETH वापरत असतील, तर असे दिसणार नाही की बिलने ॲलिसला काही हस्तांतरित केले आहे, जरी ॲलिसने गुप्त पत्त्यावरून तिच्या ज्ञात मोहीम पत्त्यावर त्वरित पैसे काढले तरीही.

एक गुप्त-पत्ता ॲप्लिकेशन लिहिणे

हा लेख GitHub वर उपलब्ध (opens in a new tab) असलेल्या गुप्त-पत्ता ॲप्लिकेशनबद्दल स्पष्ट करतो.

साधने

एक टाइपस्क्रिप्ट गुप्त पत्ता लायब्ररी (opens in a new tab) आहे जी आपण वापरू शकतो. तथापि, कूटलेखन ऑपरेशन्स CPU-केंद्रित असू शकतात. मी त्यांना Rust (opens in a new tab) सारख्या संकलित भाषेत कार्यान्वित करण्यास प्राधान्य देतो, आणि ब्राउझरमध्ये कोड चालवण्यासाठी WASM (opens in a new tab) वापरतो.

आम्ही Vite (opens in a new tab) आणि React (opens in a new tab) वापरणार आहोत. ही उद्योग-मानक साधने आहेत; जर तुम्हाला त्यांच्याशी परिचय नसेल, तर तुम्ही हे ट्यूटोरियल वापरू शकता. Vite वापरण्यासाठी, आम्हाला Node ची आवश्यकता आहे.

गुप्त पत्ते प्रत्यक्षात पहा

  1. आवश्यक साधने स्थापित करा: Rust (opens in a new tab) आणि Node (opens in a new tab).

  2. GitHub रिपॉझिटरी क्लोन करा.

    1git clone https://github.com/qbzzt/251022-stealth-addresses.git
    2cd 251022-stealth-addresses
  3. पूर्वापेक्षित गोष्टी स्थापित करा आणि Rust कोड संकलित करा.

    1cd src/rust-wasm
    2rustup target add wasm32-unknown-unknown
    3cargo install wasm-pack
    4wasm-pack build --target web
  4. वेब सर्व्हर सुरू करा.

    1cd ../..
    2npm install
    3npm run dev
  5. ॲप्लिकेशन (opens in a new tab) वर ब्राउझ करा. या ॲप्लिकेशन पृष्ठावर दोन फ्रेम आहेत: एक ॲलिसच्या वापरकर्ता इंटरफेससाठी आणि दुसरी बिलच्या. दोन फ्रेम संवाद साधत नाहीत; त्या फक्त सोयीसाठी एकाच पृष्ठावर आहेत.

  6. ॲलिस म्हणून, एक गुप्त मेटा-पत्ता तयार करा वर क्लिक करा. हे नवीन गुप्त पत्ता आणि संबंधित खाजगी की प्रदर्शित करेल. गुप्त मेटा-पत्ता क्लिपबोर्डवर कॉपी करा.

  7. बिल म्हणून, नवीन गुप्त मेटा-पत्ता पेस्ट करा आणि एक पत्ता तयार करा वर क्लिक करा. हे तुम्हाला ॲलिससाठी निधी देण्यासाठी पत्ता देते.

  8. पत्ता आणि बिलची सार्वजनिक की कॉपी करा आणि त्यांना ॲलिसच्या वापरकर्ता इंटरफेसच्या "बिलद्वारे तयार केलेल्या पत्त्यासाठी खाजगी की" क्षेत्रात पेस्ट करा. एकदा ती क्षेत्रे भरली की, तुम्हाला त्या पत्त्यावरील मालमत्तांमध्ये प्रवेश करण्यासाठी खाजगी की दिसेल.

  9. खाजगी की पत्त्याशी जुळते याची खात्री करण्यासाठी तुम्ही एक ऑनलाइन कॅल्क्युलेटर (opens in a new tab) वापरू शकता.

प्रोग्राम कसा कार्य करतो

WASM घटक

WASM मध्ये संकलित होणारा स्त्रोत कोड Rust (opens in a new tab) मध्ये लिहिलेला आहे. तुम्ही ते src/rust_wasm/src/lib.rs (opens in a new tab) मध्ये पाहू शकता. हा कोड प्रामुख्याने JavaScript कोड आणि eth-stealth-addresses लायब्ररी (opens in a new tab) यांच्यातील इंटरफेस आहे.

Cargo.toml

Rust मधील Cargo.toml (opens in a new tab) हे JavaScript मधील package.json (opens in a new tab) प्रमाणेच आहे. यात पॅकेज माहिती, अवलंबित्व घोषणा इत्यादींचा समावेश आहे.

1[package]
2name = "rust-wasm"
3version = "0.1.0"
4edition = "2024"
5
6[dependencies]
7eth-stealth-addresses = "0.1.0"
8hex = "0.4.3"
9wasm-bindgen = "0.2.104"
10getrandom = { version = "0.2", features = ["js"] }
सर्व दाखवा

getrandom (opens in a new tab) पॅकेजला यादृच्छिक मूल्ये तयार करण्याची आवश्यकता आहे. हे केवळ अल्गोरिदमिक माध्यमांनी केले जाऊ शकत नाही; त्याला एंट्रॉपीचा स्त्रोत म्हणून भौतिक प्रक्रियेत प्रवेश आवश्यक आहे. ही व्याख्या निर्दिष्ट करते की आम्ही ज्या ब्राउझरमध्ये चालवत आहोत त्याला विचारून आम्ही ती एंट्रॉपी मिळवू.

1console_error_panic_hook = "0.1.7"

ही लायब्ररी (opens in a new tab) आम्हाला अधिक अर्थपूर्ण त्रुटी संदेश देते जेव्हा WASM कोड पॅनिक होतो आणि पुढे चालू शकत नाही.

1[lib]
2crate-type = ["cdylib", "rlib"]

WASM कोड तयार करण्यासाठी आवश्यक असलेला आउटपुट प्रकार.

lib.rs

हा खरा Rust कोड आहे.

1use wasm_bindgen::prelude::*;

Rust मधून WASM पॅकेज तयार करण्याच्या व्याख्या. ते येथे (opens in a new tab) दस्तऐवजीकरण केलेले आहेत.

1use eth_stealth_addresses::{
2 generate_stealth_meta_address,
3 generate_stealth_address,
4 compute_stealth_key
5};

आम्हाला eth-stealth-addresses लायब्ररी (opens in a new tab) मधून आवश्यक असलेली फंक्शन्स.

1use hex::{decode,encode};

Rust सामान्यतः मूल्यांसाठी बाइट अॅरे (opens in a new tab) ([u8; <size>]) वापरते. परंतु JavaScript मध्ये, आम्ही सामान्यतः हेक्साडेसिमल स्ट्रिंग वापरतो. hex लायब्ररी (opens in a new tab) आमच्यासाठी एका प्रतिनिधित्वातून दुसऱ्यामध्ये भाषांतर करते.

1#[wasm_bindgen]

JavaScript मधून हे फंक्शन कॉल करण्यासाठी WASM बाइंडिंग तयार करा.

1pub fn wasm_generate_stealth_meta_address() -> String {

अनेक फील्ड असलेले ऑब्जेक्ट परत करण्याचा सर्वात सोपा मार्ग म्हणजे JSON स्ट्रिंग परत करणे.

1 let (address, spend_private_key, view_private_key) =
2 generate_stealth_meta_address();

generate_stealth_meta_address (opens in a new tab) तीन फील्ड परत करते:

  • मेटा-पत्ता (Kpub आणि Vpub)
  • पाहण्याची खाजगी की (Vpriv)
  • खर्च करण्याची खाजगी की (Kpriv)

टपल (opens in a new tab) सिंटॅक्स आम्हाला ती मूल्ये पुन्हा वेगळी करू देतो.

1 format!("{{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}}",
2 encode(address),
3 encode(view_private_key),
4 encode(spend_private_key)
5 )
6}

JSON-एनकोडेड स्ट्रिंग तयार करण्यासाठी format! (opens in a new tab) मॅक्रो वापरा. अॅरेला हेक्स स्ट्रिंगमध्ये बदलण्यासाठी hex::encode (opens in a new tab) वापरा.

1fn str_to_array<const N: usize>(s: &str) -> Option<[u8; N]> {

हे फंक्शन हेक्स स्ट्रिंगला (JavaScript द्वारे प्रदान केलेले) बाइट अॅरेमध्ये बदलते. आम्ही JavaScript कोडद्वारे प्रदान केलेली मूल्ये पार्स करण्यासाठी याचा वापर करतो. Rust अॅरे आणि व्हेक्टर कसे हाताळते त्यामुळे हे फंक्शन क्लिष्ट आहे.

<const N: usize> अभिव्यक्तीला जेनेरिक (opens in a new tab) म्हणतात. N हे एक पॅरामीटर आहे जे परत केलेल्या अॅरेच्या लांबीवर नियंत्रण ठेवते. फंक्शनला प्रत्यक्षात str_to_array::<n> असे म्हणतात, जिथे n ही अॅरेची लांबी आहे.

परत केलेले मूल्य Option<[u8; N]> आहे, याचा अर्थ परत केलेला अॅरे पर्यायी (opens in a new tab) आहे. Rust मध्ये अयशस्वी होऊ शकणाऱ्या फंक्शन्ससाठी हा एक सामान्य नमुना आहे.

उदाहरणार्थ, जर आपण str_to_array::10("bad060a7") कॉल केले, तर फंक्शनने दहा-मूल्यांची अॅरे परत करणे अपेक्षित आहे, परंतु इनपुट फक्त चार बाइट्सचे आहे. फंक्शन अयशस्वी होणे आवश्यक आहे, आणि ते None परत करून तसे करते. str_to_array::4("bad060a7") साठी परत केलेले मूल्य Some<[0xba, 0xd0, 0x60, 0xa7]> असेल.

1 // decode returns Result<Vec<u8>, _>
2 let vec = decode(s).ok()?;

hex::decode (opens in a new tab) फंक्शन Result<Vec<u8>, FromHexError> परत करते. Result (opens in a new tab) प्रकारात एकतर यशस्वी परिणाम (Ok(value)) किंवा एक त्रुटी (Err(error)) असू शकते.

.ok() पद्धत Result ला Option मध्ये रूपांतरित करते, ज्याचे मूल्य यशस्वी झाल्यास Ok() मूल्य किंवा अयशस्वी झाल्यास None असते. शेवटी, प्रश्नचिन्ह ऑपरेटर (opens in a new tab) Option रिक्त असल्यास वर्तमान फंक्शन रद्द करतो आणि None परत करतो. अन्यथा, ते मूल्य अनरॅप करते आणि ते परत करते (या प्रकरणात, vec ला मूल्य नियुक्त करण्यासाठी).

त्रुटी हाताळण्याची ही एक विचित्र गुंतागुंतीची पद्धत वाटते, परंतु Result आणि Option हे सुनिश्चित करतात की सर्व त्रुटी, एका ना कोणत्या मार्गाने हाताळल्या जातात.

1 if vec.len() != N { return None; }

जर बाइट्सची संख्या चुकीची असेल, तर ते अपयश आहे, आणि आम्ही None परत करतो.

1 // try_into consumes vec and attempts to make [u8; N]
2 let array: [u8; N] = vec.try_into().ok()?;

Rust मध्ये दोन अॅरे प्रकार आहेत. अॅरे (opens in a new tab) चा आकार निश्चित असतो. व्हेक्टर (opens in a new tab) वाढू आणि लहान होऊ शकतात. hex::decode एक व्हेक्टर परत करतो, परंतु eth_stealth_addresses लायब्ररीला अॅरे प्राप्त करायचे आहेत. .try_into() (opens in a new tab) एका मूल्याला दुसऱ्या प्रकारात रूपांतरित करते, उदाहरणार्थ, व्हेक्टरला अॅरेमध्ये.

1 Some(array)
2}

Rust तुम्हाला फंक्शनच्या शेवटी मूल्य परत करताना return (opens in a new tab) कीवर्ड वापरण्याची आवश्यकता नाही.

1#[wasm_bindgen]
2pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option<String> {

हे फंक्शन एक सार्वजनिक मेटा-पत्ता प्राप्त करते, ज्यात Vpub आणि Kpub दोन्ही समाविष्ट आहेत. ते गुप्त पत्ता, प्रकाशित करण्यासाठी सार्वजनिक की (Rpub), आणि एक-बाइट स्कॅन मूल्य परत करते जे ॲलिसच्या मालकीचे कोणते प्रकाशित पत्ते असू शकतात हे ओळखण्यास गती देते.

स्कॅन मूल्य सामायिक गुप्त (S = GRprivVpriv) चा भाग आहे. हे मूल्य ॲलिससाठी उपलब्ध आहे, आणि ते तपासणे f(Kpub+G*hash(S)) प्रकाशित पत्त्याच्या बरोबर आहे की नाही हे तपासण्यापेक्षा खूप वेगवान आहे.

1 let (address, r_pub, scan) =
2 generate_stealth_address(&str_to_array::<66>(stealth_address)?);

आम्ही लायब्ररीचे generate_stealth_address (opens in a new tab) वापरतो.

1 format!("{{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}}",
2 encode(address),
3 encode(r_pub),
4 encode(&[scan])
5 ).into()
6}

JSON-एनकोडेड आउटपुट स्ट्रिंग तयार करा.

1#[wasm_bindgen]
2pub fn wasm_compute_stealth_key(
3 address: &str,
4 bill_pub_key: &str,
5 view_private_key: &str,
6 spend_private_key: &str
7) -> Option<String> {
8 .
9 .
10 .
11}
सर्व दाखवा

हे फंक्शन पत्त्यावरून (Rpriv) पैसे काढण्यासाठी खाजगी की मोजण्यासाठी लायब्ररीच्या compute_stealth_key (opens in a new tab) चा वापर करते. या गणनेसाठी ही मूल्ये आवश्यक आहेत:

  • पत्ता (पत्ता=f(Ppub))
  • बिलद्वारे तयार केलेली सार्वजनिक की (Rpub)
  • पाहण्याची खाजगी की (Vpriv)
  • खर्च करण्याची खाजगी की (Kpriv)
1#[wasm_bindgen(start)]

#[wasm_bindgen(start)] (opens in a new tab) निर्दिष्ट करते की WASM कोड सुरू झाल्यावर फंक्शन कार्यान्वित केले जाते.

1pub fn main() {
2 console_error_panic_hook::set_once();
3}

हा कोड निर्दिष्ट करतो की पॅनिक आउटपुट JavaScript कन्सोलवर पाठवले जावे. ते प्रत्यक्षात पाहण्यासाठी, ॲप्लिकेशन वापरा आणि बिलला एक अवैध मेटा-पत्ता द्या (फक्त एक हेक्साडेसिमल अंक बदला). तुम्हाला JavaScript कन्सोलमध्ये ही त्रुटी दिसेल:

1rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9:
2assertion `left == right` failed
3 left: 0
4 right: 1

त्यानंतर स्टॅक ट्रेस येईल. नंतर बिलला वैध मेटा-पत्ता द्या, आणि ॲलिसला एकतर अवैध पत्ता किंवा अवैध सार्वजनिक की द्या. तुम्हाला ही त्रुटी दिसेल:

1rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/eth-stealth-addresses-0.1.0/src/lib.rs:78:9:
2keys do not generate stealth address

पुन्हा, त्यानंतर स्टॅक ट्रेस येईल.

वापरकर्ता इंटरफेस

वापरकर्ता इंटरफेस React (opens in a new tab) वापरून लिहिलेला आहे आणि Vite (opens in a new tab) द्वारे सर्व्ह केला जातो. तुम्ही या ट्यूटोरियल चा वापर करून त्यांच्याबद्दल शिकू शकता. येथे WAGMI (opens in a new tab) ची गरज नाही कारण आम्ही थेट ब्लॉकचेन किंवा वॉलेटशी संवाद साधत नाही.

वापरकर्ता इंटरफेसचा एकमेव अस्पष्ट भाग म्हणजे WASM कनेक्टिव्हिटी. हे कसे कार्य करते ते येथे आहे.

vite.config.js

या फाइलमध्ये Vite कॉन्फिगरेशन (opens in a new tab) आहे.

1import { defineConfig } from 'vite'
2import react from '@vitejs/plugin-react'
3import wasm from "vite-plugin-wasm";
4
5// https://vite.dev/config/
6export default defineConfig({
7 plugins: [react(), wasm()],
8})

आम्हाला दोन Vite प्लगइनची आवश्यकता आहे: react (opens in a new tab) आणि wasm (opens in a new tab).

App.jsx

ही फाइल ॲप्लिकेशनचा मुख्य घटक आहे. हे एक कंटेनर आहे ज्यात दोन घटक आहेत: Alice आणि Bill, त्या वापरकर्त्यांसाठी वापरकर्ता इंटरफेस. WASM साठी संबंधित भाग म्हणजे इनिशियलायझेशन कोड.

1import init from './rust-wasm/pkg/rust_wasm.js'

जेव्हा आपण wasm-pack (opens in a new tab) वापरतो, तेव्हा ते दोन फाइल्स तयार करते ज्या आपण येथे वापरतो: प्रत्यक्ष कोड असलेली एक wasm फाइल (येथे, src/rust-wasm/pkg/rust_wasm_bg.wasm) आणि ते वापरण्यासाठी व्याख्या असलेली एक JavaScript फाइल (येथे, src/rust_wasm/pkg/rust_wasm.js). त्या JavaScript फाइलचा डीफॉल्ट एक्सपोर्ट हा कोड आहे जो WASM सुरू करण्यासाठी चालवणे आवश्यक आहे.

1function App() {
2 .
3 .
4 .
5 useEffect(() => {
6 const loadWasm = async () => {
7 try {
8 await init();
9 setWasmReady(true)
10 } catch (err) {
11 console.error('Error loading wasm:', err)
12 alert("Wasm error: " + err)
13 }
14 }
15
16 loadWasm()
17 }, []
18 )
सर्व दाखवा

useEffect हुक (opens in a new tab) तुम्हाला एक फंक्शन निर्दिष्ट करू देतो जे स्टेट व्हेरिएबल्स बदलल्यावर कार्यान्वित होते. येथे, स्टेट व्हेरिएबल्सची सूची रिकामी ([]) आहे, त्यामुळे हे फंक्शन पृष्ठ लोड झाल्यावर फक्त एकदाच कार्यान्वित होते.

इफेक्ट फंक्शन त्वरित परत आले पाहिजे. असिंक्रोनस कोड वापरण्यासाठी, जसे की WASM init (ज्याला .wasm फाइल लोड करावी लागते आणि त्यामुळे वेळ लागतो) आम्ही एक अंतर्गत async (opens in a new tab) फंक्शन परिभाषित करतो आणि ते await शिवाय चालवतो.

Bill.jsx

हा बिलसाठी वापरकर्ता इंटरफेस आहे. त्यात एकच क्रिया आहे, ॲलिसने प्रदान केलेल्या गुप्त मेटा-पत्त्यावर आधारित पत्ता तयार करणे.

1import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js'

डीफॉल्ट एक्सपोर्ट व्यतिरिक्त, wasm-pack द्वारे तयार केलेला JavaScript कोड WASM कोडमधील प्रत्येक फंक्शनसाठी एक फंक्शन एक्सपोर्ट करतो.

1 <button onClick={() => {
2 setPublicAddress(JSON.parse(wasm_generate_stealth_address(stealthMetaAddress)))
3 }}>

WASM फंक्शन्स कॉल करण्यासाठी, आम्ही फक्त wasm-pack द्वारे तयार केलेल्या JavaScript फाइलद्वारे एक्सपोर्ट केलेले फंक्शन कॉल करतो.

Alice.jsx

Alice.jsx मधील कोड समान आहे, फक्त ॲलिसच्या दोन क्रिया आहेत:

  • एक मेटा-पत्ता तयार करा
  • बिलने प्रकाशित केलेल्या पत्त्यासाठी खाजगी की मिळवा

निष्कर्ष

गुप्त पत्ते हे रामबाण उपाय नाहीत; ते योग्यरित्या वापरले पाहिजेत. परंतु योग्यरित्या वापरल्यास, ते सार्वजनिक ब्लॉकचेनवर गोपनीयता सक्षम करू शकतात.

माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा (opens in a new tab).

पृष्ठ अखेरचे अद्यतन: १४ नोव्हेंबर, २०२५

हे मार्गदर्शन उपयुक्त होते का?