மறைமுக முகவரிகளைப் பயன்படுத்துதல்
நீங்கள் பில். நாம் விவாதிக்க விரும்பாத சில காரணங்களுக்காக, "ஆலிஸ் ஃபார் குயின் ஆஃப் தி வேர்ல்ட்" (Alice for Queen of the World) பிரச்சாரத்திற்கு நீங்கள் நன்கொடை அளிக்க விரும்புகிறீர்கள், மேலும் நீங்கள் நன்கொடை அளித்ததை ஆலிஸ் தெரிந்துகொள்ள வேண்டும், அப்போதுதான் அவள் வெற்றி பெற்றால் உங்களுக்கு வெகுமதி அளிப்பாள். துரதிர்ஷ்டவசமாக, அவளது வெற்றிக்கு எந்த உத்தரவாதமும் இல்லை. "கரோல் ஃபார் எம்பிரஸ் ஆஃப் தி சோலார் சிஸ்டம்" (Carol for Empress of the Solar System) என்ற ஒரு போட்டிப் பிரச்சாரம் உள்ளது. கரோல் வெற்றி பெற்று, நீங்கள் ஆலிஸுக்கு நன்கொடை அளித்ததை அவள் கண்டுபிடித்தால், நீங்கள் சிக்கலில் மாட்டுவீர்கள். எனவே உங்கள் கணக்கிலிருந்து ஆலிஸின் கணக்கிற்கு 200 ETH-ஐ உங்களால் நேரடியாகப் பரிமாற்றம் செய்ய முடியாது.
ERC-5564 (opens in a new tab)-இல் இதற்கான தீர்வு உள்ளது. அநாமதேயப் பரிமாற்றத்திற்கு மறைமுக முகவரிகளை (opens in a new tab) எவ்வாறு பயன்படுத்துவது என்பதை இந்த ERC விளக்குகிறது.
எச்சரிக்கை: மறைமுக முகவரிகளுக்குப் பின்னால் உள்ள குறியாக்கவியல், நமக்குத் தெரிந்தவரை, பாதுகாப்பானது. இருப்பினும், சாத்தியமான பக்க-சேனல் (side-channel) தாக்குதல்கள் உள்ளன. இந்த அபாயத்தைக் குறைக்க நீங்கள் என்ன செய்யலாம் என்பதை கீழே காண்பீர்கள்.
மறைமுக முகவரிகள் எவ்வாறு செயல்படுகின்றன
இந்தக் கட்டுரை மறைமுக முகவரிகளை இரண்டு வழிகளில் விளக்க முயற்சிக்கும். முதலாவது அவற்றை எவ்வாறு பயன்படுத்துவது என்பது. கட்டுரையின் மீதமுள்ள பகுதியைப் புரிந்துகொள்ள இந்தப் பகுதி போதுமானது. பின்னர், இதற்குப் பின்னால் உள்ள கணிதத்தின் விளக்கம் உள்ளது. உங்களுக்குக் குறியாக்கவியலில் ஆர்வம் இருந்தால், இந்தப் பகுதியையும் படிக்கவும்.
எளிய பதிப்பு (மறைமுக முகவரிகளை எவ்வாறு பயன்படுத்துவது)
ஆலிஸ் இரண்டு தனிப்பட்ட திறவுகோல்களை உருவாக்கி, அவற்றுக்குரிய பொது விசைகளை வெளியிடுகிறாள் (இவற்றை ஒற்றை இரட்டை-நீள மெட்டா-முகவரியாக இணைக்கலாம்). பில்லும் ஒரு தனிப்பட்ட திறவுகோலை உருவாக்கி, அதற்குரிய பொது விசையை வெளியிடுகிறார்.
ஒரு தரப்பினரின் பொது விசை மற்றும் மற்றவரின் தனிப்பட்ட திறவுகோலைப் பயன்படுத்தி, ஆலிஸ் மற்றும் பில்லுக்கு மட்டுமே தெரிந்த ஒரு பகிரப்பட்ட ரகசியத்தை நீங்கள் பெறலாம் (இதைப் பொது விசைகளிலிருந்து மட்டுமே பெற முடியாது). இந்தப் பகிரப்பட்ட ரகசியத்தைப் பயன்படுத்தி, பில் மறைமுக முகவரியைப் பெறுகிறார், மேலும் அதற்குச் சொத்துக்களை அனுப்ப முடியும்.
ஆலிஸும் பகிரப்பட்ட ரகசியத்திலிருந்து முகவரியைப் பெறுகிறாள், ஆனால் அவள் வெளியிட்ட பொது விசைகளுக்கான தனிப்பட்ட திறவுகோல்கள் அவளுக்குத் தெரியும் என்பதால், அந்த முகவரியிலிருந்து பணத்தை எடுக்க அனுமதிக்கும் தனிப்பட்ட திறவுகோலையும் அவளால் பெற முடியும்.
கணிதம் (மறைமுக முகவரிகள் ஏன் இவ்வாறு செயல்படுகின்றன)
நிலையான மறைமுக முகவரிகள், அதே அளவிலான பாதுகாப்பைப் பராமரிக்கும் அதே வேளையில், குறைவான விசை பிட்களுடன் சிறந்த செயல்திறனைப் பெற எலிப்டிக்-கர்வ் குறியாக்கவியலைப் (ECC) (opens in a new tab) பயன்படுத்துகின்றன. ஆனால் பெரும்பாலும் நாம் அதைப் புறக்கணித்துவிட்டு, வழக்கமான எண்கணிதத்தைப் பயன்படுத்துவது போல் பாசாங்கு செய்யலாம்.
அனைவருக்கும் தெரிந்த ஒரு எண் உள்ளது, G. நீங்கள் G-ஆல் பெருக்கலாம். ஆனால் ECC-இன் தன்மை காரணமாக, G-ஆல் வகுப்பது நடைமுறையில் சாத்தியமற்றது. எத்திரியத்தில் பொது விசை குறியாக்கவியல் பொதுவாகச் செயல்படும் விதம் என்னவென்றால், நீங்கள் ஒரு தனிப்பட்ட திறவுகோலான Ppriv-ஐப் பயன்படுத்திப் பரிவர்த்தனைகளில் கையொப்பமிடலாம், பின்னர் அவை Ppub = GPpriv என்ற பொது விசையால் சரிபார்க்கப்படும்.
ஆலிஸ் Kpriv மற்றும் Vpriv ஆகிய இரண்டு தனிப்பட்ட திறவுகோல்களை உருவாக்குகிறாள். Kpriv என்பது மறைமுக முகவரியிலிருந்து பணத்தைச் செலவழிக்கப் பயன்படுத்தப்படும், மேலும் Vpriv என்பது ஆலிஸுக்குச் சொந்தமான முகவரிகளைப் பார்க்கப் பயன்படுத்தப்படும். பின்னர் ஆலிஸ் பொது விசைகளை வெளியிடுகிறாள்: Kpub = GKpriv மற்றும் Vpub = GVpriv
பில் Rpriv என்ற மூன்றாவது தனிப்பட்ட திறவுகோலை உருவாக்கி, Rpub = GRpriv-ஐ ஒரு மையப் பதிவேட்டில் வெளியிடுகிறார் (பில் அதை ஆலிஸுக்கும் அனுப்பியிருக்கலாம், ஆனால் கரோல் ஒட்டுக் கேட்கிறாள் என்று நாம் கருதுகிறோம்).
பில் RprivVpub = GRprivVpriv-ஐக் கணக்கிடுகிறார், இதை ஆலிஸும் அறிந்திருப்பாள் என்று அவர் எதிர்பார்க்கிறார் (கீழே விளக்கப்பட்டுள்ளது). இந்த மதிப்பு S என்று அழைக்கப்படுகிறது, இது பகிரப்பட்ட ரகசியம். இது பில்லுக்கு Ppub = Kpub+G*hash(S) என்ற பொது விசையை அளிக்கிறது. இந்தப் பொது விசையிலிருந்து, அவர் ஒரு முகவரியைக் கணக்கிட்டு, தான் விரும்பும் எந்த வளங்களையும் அதற்கு அனுப்ப முடியும். எதிர்காலத்தில், ஆலிஸ் வெற்றி பெற்றால், வளங்கள் தன்னிடம் இருந்து வந்தன என்பதை நிரூபிக்க பில் அவளிடம் Rpriv-ஐக் கூறலாம்.
ஆலிஸ் RpubVpriv = GRprivVpriv-ஐக் கணக்கிடுகிறாள். இது அவளுக்கு அதே பகிரப்பட்ட ரகசியமான S-ஐ அளிக்கிறது. அவளுக்குத் தனிப்பட்ட திறவுகோலான Kpriv தெரியும் என்பதால், அவளால் Ppriv = Kpriv+hash(S)-ஐக் கணக்கிட முடியும். இந்தத் திறவுகோல் Ppub = GPpriv = GKpriv+G*hash(S) = Kpub+G*hash(S) என்பதிலிருந்து கிடைக்கும் முகவரியில் உள்ள சொத்துக்களை அணுக அவளை அனுமதிக்கிறது.
ஆலிஸ் டேவின் வேர்ல்ட் டாமினேஷன் கேம்பெயின் சர்வீசஸுக்கு (Dave's World Domination Campaign Services) துணை ஒப்பந்தம் செய்ய அனுமதிக்க, எங்களிடம் ஒரு தனிப் பார்வைத் திறவுகோல் உள்ளது. பொது முகவரிகளை டேவ் தெரிந்துகொள்ளவும், அதிகப் பணம் கிடைக்கும்போது அவளுக்குத் தெரிவிக்கவும் ஆலிஸ் தயாராக இருக்கிறாள், ஆனால் அவர் தனது பிரச்சாரப் பணத்தைச் செலவழிப்பதை அவள் விரும்பவில்லை.
பார்ப்பதற்கும் செலவழிப்பதற்கும் தனித்தனித் திறவுகோல்கள் பயன்படுத்தப்படுவதால், ஆலிஸ் டேவுக்கு Vpriv-ஐக் கொடுக்கலாம். பின்னர் டேவ் S = RpubVpriv = GRprivVpriv-ஐக் கணக்கிடலாம், அந்த வகையில் பொது விசைகளைப் பெறலாம் (Ppub = Kpub+G*hash(S)). ஆனால் Kpriv இல்லாமல் டேவால் தனிப்பட்ட திறவுகோலைப் பெற முடியாது.
சுருக்கமாகக் கூறினால், வெவ்வேறு பங்கேற்பாளர்களுக்குத் தெரிந்த மதிப்புகள் இவை.
| ஆலிஸ் | வெளியிடப்பட்டது | பில் | டேவ் |
|---|---|---|---|
| G | G | G | G |
| Kpriv | - | - | - |
| Vpriv | - | - | Vpriv |
| Kpub = GKpriv | Kpub | Kpub | Kpub |
| Vpub = GVpriv | Vpub | Vpub | Vpub |
| - | - | Rpriv | - |
| Rpub | Rpub | Rpub = GRpriv | Rpub |
| S = RpubVpriv = GRprivVpriv | - | S = RprivVpub = GRprivVpriv | S = RpubVpriv = GRprivVpriv |
| Ppub = Kpub+G*hash(S) | - | Ppub = Kpub+G*hash(S) | Ppub = Kpub+G*hash(S) |
| Address=f(Ppub) | - | Address=f(Ppub) | Address=f(Ppub) |
| Ppriv = Kpriv+hash(S) | - | - | - |
மறைமுக முகவரிகள் தவறாகப் போகும்போது
தொகுதிச்சங்கிலியில் எந்த ரகசியங்களும் இல்லை. மறைமுக முகவரிகள் உங்களுக்குத் தனியுரிமையை வழங்க முடியும் என்றாலும், அந்தத் தனியுரிமை போக்குவரத்துப் பகுப்பாய்விற்கு (traffic analysis) ஆளாகக்கூடும். ஒரு சிறிய உதாரணத்தை எடுத்துக்கொண்டால், பில் ஒரு முகவரிக்கு நிதியளித்து, உடனடியாக ஒரு Rpub மதிப்பை வெளியிட ஒரு பரிவர்த்தனையை அனுப்புகிறார் என்று கற்பனை செய்து பாருங்கள். ஆலிஸின் Vpriv இல்லாமல், இது ஒரு மறைமுக முகவரி என்று நாம் உறுதியாகக் கூற முடியாது, ஆனால் அப்படித்தான் யூகிக்க முடியும். பின்னர், அந்த முகவரியிலிருந்து அனைத்து ETH-ஐயும் ஆலிஸின் பிரச்சார நிதி முகவரிக்குப் பரிமாற்றம் செய்யும் மற்றொரு பரிவர்த்தனையை நாம் காண்கிறோம். நம்மால் அதை நிரூபிக்க முடியாமல் போகலாம், ஆனால் பில் ஆலிஸின் பிரச்சாரத்திற்கு நன்கொடை அளித்திருக்க வாய்ப்புள்ளது. கரோல் நிச்சயமாக அப்படித்தான் நினைப்பாள்.
பில் Rpub-இன் வெளியீட்டை மறைமுக முகவரிக்கு நிதியளிப்பதிலிருந்து பிரிப்பது எளிது (வெவ்வேறு நேரங்களில், வெவ்வேறு முகவரிகளிலிருந்து அவற்றைச் செய்யலாம்). இருப்பினும், அது போதாது. கரோல் தேடும் முறை என்னவென்றால், பில் ஒரு முகவரிக்கு நிதியளிக்கிறார், பின்னர் ஆலிஸின் பிரச்சார நிதி அதிலிருந்து பணத்தை எடுக்கிறது.
இதற்கு ஒரு தீர்வு, ஆலிஸின் பிரச்சாரம் பணத்தை நேரடியாக எடுக்காமல், மூன்றாம் தரப்பினருக்குச் செலுத்த அதைப் பயன்படுத்துவதாகும். ஆலிஸின் பிரச்சாரம் டேவின் வேர்ல்ட் டாமினேஷன் கேம்பெயின் சர்வீசஸுக்கு 10 ETH-ஐ அனுப்பினால், பில் டேவின் வாடிக்கையாளர்களில் ஒருவருக்கு நன்கொடை அளித்தார் என்பது மட்டுமே கரோலுக்குத் தெரியும். டேவுக்குப் போதுமான வாடிக்கையாளர்கள் இருந்தால், தன்னுடன் போட்டியிடும் ஆலிஸுக்குப் பில் நன்கொடை அளித்தாரா அல்லது கரோல் கவலைப்படாத ஆடம், ஆல்பர்ட் அல்லது அபிகெய்லுக்கு நன்கொடை அளித்தாரா என்பதை கரோலால் அறிய முடியாது. ஆலிஸ் கட்டணத்துடன் ஒரு ஹாஷ் செய்யப்பட்ட மதிப்பைச் சேர்க்கலாம், பின்னர் அது தனது நன்கொடை என்பதை நிரூபிக்க டேவுக்கு ப்ரீஇமேஜை (preimage) வழங்கலாம். மாற்றாக, மேலே குறிப்பிட்டுள்ளபடி, ஆலிஸ் டேவுக்குத் தனது Vpriv-ஐக் கொடுத்தால், பணம் யாரிடமிருந்து வந்தது என்பது அவருக்கு ஏற்கனவே தெரியும்.
இந்தத் தீர்வில் உள்ள முக்கியப் பிரச்சனை என்னவென்றால், அந்த ரகசியம் பில்லுக்குப் பயனளிக்கும்போது ஆலிஸ் ரகசியத்தைப் பற்றிக் கவலைப்பட வேண்டும். ஆலிஸ் தனது நற்பெயரைப் பராமரிக்க விரும்பலாம், அதனால் பில்லின் நண்பரான பாபும் அவளுக்கு நன்கொடை அளிப்பார். ஆனால் பில்லை அம்பலப்படுத்துவதில் அவளுக்கு எந்த ஆட்சேபனையும் இல்லாமல் இருக்கவும் வாய்ப்புள்ளது, ஏனென்றால் கரோல் வெற்றி பெற்றால் என்ன நடக்கும் என்று அவர் பயப்படுவார். பில் ஆலிஸுக்கு இன்னும் அதிக ஆதரவை வழங்க நேரிடலாம்.
பல மறைமுக அடுக்குகளைப் பயன்படுத்துதல்
பில்லின் தனியுரிமையைப் பாதுகாக்க ஆலிஸை நம்பியிருப்பதற்குப் பதிலாக, பில் அதைத் தானே செய்யலாம். அவர் பாப் மற்றும் பெல்லா என்ற கற்பனையான நபர்களுக்காகப் பல மெட்டா-முகவரிகளை உருவாக்க முடியும். பில் பின்னர் பாப்பிற்கு ETH-ஐ அனுப்புகிறார், மேலும் "பாப்" (உண்மையில் பில்) அதை பெல்லாவுக்கு அனுப்புகிறார். "பெல்லா" (அவரும் பில் தான்) அதை ஆலிஸுக்கு அனுப்புகிறார்.
கரோல் இன்னும் போக்குவரத்துப் பகுப்பாய்வு செய்து பில்-டு-பாப்-டு-பெல்லா-டு-ஆலிஸ் (Bill-to-Bob-to-Bella-to-Alice) பைப்லைனைக் காண முடியும். இருப்பினும், "பாப்" மற்றும் "பெல்லா" ஆகியோரும் மற்ற நோக்கங்களுக்காக ETH-ஐப் பயன்படுத்தினால், ஆலிஸ் உடனடியாக மறைமுக முகவரியிலிருந்து தனக்குத் தெரிந்த பிரச்சார முகவரிக்குப் பணத்தை எடுத்தாலும், பில் ஆலிஸுக்கு எதையும் பரிமாற்றம் செய்ததாகத் தோன்றாது.
மறைமுக முகவரிப் பயன்பாட்டை எழுதுதல்
இந்தக் கட்டுரை GitHub-இல் கிடைக்கும் (opens in a new tab) ஒரு மறைமுக முகவரிப் பயன்பாட்டை விளக்குகிறது.
கருவிகள்
நாம் பயன்படுத்தக்கூடிய ஒரு TypeScript மறைமுக முகவரி நிரலகம் (opens in a new tab) உள்ளது. இருப்பினும், குறியாக்கவியல் செயல்பாடுகள் CPU-ஐ அதிகம் பயன்படுத்தக்கூடியவை. அவற்றை Rust (opens in a new tab) போன்ற தொகுக்கப்பட்ட மொழியில் (compiled language) செயல்படுத்தவும், உலாவியில் குறியீட்டை இயக்க WASM (opens in a new tab)-ஐப் பயன்படுத்தவும் நான் விரும்புகிறேன்.
நாம் Vite (opens in a new tab) மற்றும் React (opens in a new tab)-ஐப் பயன்படுத்தப் போகிறோம். இவை தொழில்துறை-தரமான கருவிகள்; உங்களுக்கு இவற்றில் பரிச்சயம் இல்லை என்றால், நீங்கள் இந்த வழிகாட்டியைப் பயன்படுத்தலாம். Vite-ஐப் பயன்படுத்த, நமக்கு Node தேவை.
மறைமுக முகவரிகள் செயல்படுவதைப் பார்க்கவும்
-
தேவையான கருவிகளை நிறுவவும்: Rust (opens in a new tab) மற்றும் Node (opens in a new tab).
-
GitHub களஞ்சியத்தை (repository) குளோன் செய்யவும்.
git clone https://github.com/qbzzt/251022-stealth-addresses.git cd 251022-stealth-addresses -
முன்நிபந்தனைகளை நிறுவி, Rust குறியீட்டைத் தொகுக்கவும்.
cd src/rust-wasm rustup target add wasm32-unknown-unknown cargo install wasm-pack wasm-pack build --target web -
இணையச் சேவையகத்தைத் தொடங்கவும்.
cd ../.. npm install npm run dev -
பயன்பாட்டிற்குச் (opens in a new tab) செல்லவும். இந்தப் பயன்பாட்டுப் பக்கத்தில் இரண்டு பிரேம்கள் உள்ளன: ஒன்று ஆலிஸின் பயனர் இடைமுகத்திற்கும் மற்றொன்று பில்லிற்கும். இரண்டு பிரேம்களும் தொடர்பு கொள்ளாது; வசதிக்காக அவை ஒரே பக்கத்தில் மட்டுமே உள்ளன.
-
ஆலிஸாக, Generate a Stealth Meta-Address என்பதைக் கிளிக் செய்யவும். இது புதிய மறைமுக முகவரி மற்றும் அவற்றுக்குரிய தனிப்பட்ட திறவுகோல்களைக் காண்பிக்கும். மறைமுக மெட்டா-முகவரியைக் கிளிப்போர்டுக்கு நகலெடுக்கவும்.
-
பில்லாக, புதிய மறைமுக மெட்டா-முகவரியை ஒட்டி, Generate an address என்பதைக் கிளிக் செய்யவும். இது ஆலிஸுக்கு நிதியளிப்பதற்கான முகவரியை உங்களுக்கு வழங்குகிறது.
-
முகவரி மற்றும் பில்லின் பொது விசையை நகலெடுத்து, ஆலிஸின் பயனர் இடைமுகத்தின் "Private key for address generated by Bill" பகுதியில் அவற்றை ஒட்டவும். அந்தப் புலங்கள் நிரப்பப்பட்டவுடன், அந்த முகவரியில் உள்ள சொத்துக்களை அணுகுவதற்கான தனிப்பட்ட திறவுகோலை நீங்கள் காண்பீர்கள்.
-
தனிப்பட்ட திறவுகோல் முகவரிக்கு ஒத்திருப்பதை உறுதிசெய்ய நீங்கள் ஒரு ஆன்லைன் கால்குலேட்டரைப் (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)-க்கு ஒப்பானது. இது தொகுப்புத் தகவல், சார்புநிலை அறிவிப்புகள் (dependency declarations) போன்றவற்றைக் கொண்டுள்ளது.
[package]
name = "rust-wasm"
version = "0.1.0"
edition = "2024"
[dependencies]
eth-stealth-addresses = "0.1.0"
hex = "0.4.3"
wasm-bindgen = "0.2.104"
getrandom = { version = "0.2", features = ["js"] }
getrandom (opens in a new tab) தொகுப்பு சீரற்ற மதிப்புகளை உருவாக்க வேண்டும். அதைத் தூய அல்காரிதமிக் வழிகளில் செய்ய முடியாது; அதற்கு என்ட்ரோபியின் ஆதாரமாக ஒரு இயற்பியல் செயல்முறைக்கான அணுகல் தேவை. நாம் இயங்கும் உலாவியைக் கேட்பதன் மூலம் அந்த என்ட்ரோபியைப் பெறுவோம் என்பதை இந்த வரையறை குறிப்பிடுகிறது.
console_error_panic_hook = "0.1.7"
WASM குறியீடு பீதியடைந்து (panics) தொடர முடியாதபோது, இந்த நிரலகம் (opens in a new tab) நமக்கு மிகவும் அர்த்தமுள்ள பிழைச் செய்திகளை வழங்குகிறது.
[lib]
crate-type = ["cdylib", "rlib"]
WASM குறியீட்டை உருவாக்கத் தேவையான வெளியீட்டு வகை.
lib.rs
இது உண்மையான Rust குறியீடு.
use wasm_bindgen::prelude::*;
Rust-இலிருந்து ஒரு WASM தொகுப்பை உருவாக்குவதற்கான வரையறைகள். அவை இங்கே (opens in a new tab) ஆவணப்படுத்தப்பட்டுள்ளன.
use eth_stealth_addresses::{
generate_stealth_meta_address,
generate_stealth_address,
compute_stealth_key
};
eth-stealth-addresses நிரலகத்திலிருந்து (opens in a new tab) நமக்குத் தேவையான செயல்பாடுகள்.
use hex::{decode,encode};
Rust பொதுவாக மதிப்புகளுக்கு பைட் அணிகளைப் (arrays) (opens in a new tab) ([u8; <size>]) பயன்படுத்துகிறது. ஆனால் JavaScript-இல், நாம் பொதுவாக ஹெக்ஸாடெசிமல் சரங்களைப் பயன்படுத்துகிறோம். hex நிரலகம் (opens in a new tab) நமக்காக ஒரு பிரதிநிதித்துவத்திலிருந்து மற்றொன்றுக்கு மொழிபெயர்க்கிறது.
#[wasm_bindgen]
JavaScript-இலிருந்து இந்தச் செயல்பாட்டை அழைக்க WASM பைண்டிங்குகளை (bindings) உருவாக்கவும்.
pub fn wasm_generate_stealth_meta_address() -> String {
பல புலங்களைக் கொண்ட ஒரு பொருளைத் திருப்பி அனுப்புவதற்கான எளிதான வழி, ஒரு JSON சரத்தைத் திருப்பி அனுப்புவதாகும்.
let (address, spend_private_key, view_private_key) =
generate_stealth_meta_address();
generate_stealth_meta_address (opens in a new tab) மூன்று புலங்களைத் திருப்பி அனுப்புகிறது:
- மெட்டா-முகவரி (Kpub மற்றும் Vpub)
- பார்க்கும் தனிப்பட்ட திறவுகோல் (Vpriv)
- செலவழிக்கும் தனிப்பட்ட திறவுகோல் (Kpriv)
டூப்பிள் (tuple) (opens in a new tab) தொடரியல் அந்த மதிப்புகளை மீண்டும் பிரிக்க அனுமதிக்கிறது.
format!("{{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}}",
encode(address),
encode(view_private_key),
encode(spend_private_key)
)
}
JSON-குறியிடப்பட்ட சரத்தை உருவாக்க format! (opens in a new tab) மேக்ரோவைப் பயன்படுத்தவும். அணிகளை ஹெக்ஸ் சரங்களாக மாற்ற hex::encode (opens in a new tab)-ஐப் பயன்படுத்தவும்.
fn str_to_array<const N: usize>(s: &str) -> Option<[u8; N]> {
இந்தச் செயல்பாடு ஒரு ஹெக்ஸ் சரத்தை (JavaScript-ஆல் வழங்கப்பட்டது) பைட் அணியாக மாற்றுகிறது. JavaScript குறியீட்டால் வழங்கப்பட்ட மதிப்புகளைப் பாகுபடுத்த (parse) இதைப் பயன்படுத்துகிறோம். Rust அணிகள் மற்றும் வெக்டர்களைக் கையாளும் விதம் காரணமாக இந்தச் செயல்பாடு சிக்கலானது.
<const N: usize> கோவை ஒரு ஜெனரிக் (generic) (opens in a new tab) என்று அழைக்கப்படுகிறது. N என்பது திருப்பி அனுப்பப்பட்ட அணியின் நீளத்தைக் கட்டுப்படுத்தும் ஒரு அளவுருவாகும். செயல்பாடு உண்மையில் str_to_array::<n> என்று அழைக்கப்படுகிறது, இதில் n என்பது அணியின் நீளம்.
திருப்பி அனுப்பும் மதிப்பு Option<[u8; N]> ஆகும், அதாவது திருப்பி அனுப்பப்பட்ட அணி விருப்பத்திற்குரியது (optional) (opens in a new tab). தோல்வியடையக்கூடிய செயல்பாடுகளுக்கு இது Rust-இல் ஒரு பொதுவான முறையாகும்.
எடுத்துக்காட்டாக, நாம் str_to_array::10("bad060a7")-ஐ அழைத்தால், செயல்பாடு பத்து-மதிப்பு அணியைத் திருப்பி அனுப்ப வேண்டும், ஆனால் உள்ளீடு நான்கு பைட்டுகள் மட்டுமே. செயல்பாடு தோல்வியடைய வேண்டும், மேலும் அது None-ஐத் திருப்பி அனுப்புவதன் மூலம் அவ்வாறு செய்கிறது. str_to_array::4("bad060a7")-க்கான திருப்பி அனுப்பும் மதிப்பு Some<[0xba, 0xd0, 0x60, 0xa7]> ஆக இருக்கும்.
// decode ஆனது Result<Vec<u8>, _> ஐ திருப்புகிறது
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 ஆகவோ இருக்கும். இறுதியாக, Option காலியாக இருந்தால், கேள்விக்குறி ஆபரேட்டர் (opens in a new tab) தற்போதைய செயல்பாடுகளை நிறுத்திவிட்டு None-ஐத் திருப்பி அனுப்புகிறது. இல்லையெனில், அது மதிப்பை அன்ராப் (unwrap) செய்து அதைத் திருப்பி அனுப்புகிறது (இந்த நிலையில், vec-க்கு ஒரு மதிப்பை ஒதுக்க).
இது பிழைகளைக் கையாள ஒரு விசித்திரமான சிக்கலான முறை போல் தெரிகிறது, ஆனால் Result மற்றும் Option ஆகியவை அனைத்துப் பிழைகளும் ஏதோ ஒரு வகையில் கையாளப்படுவதை உறுதி செய்கின்றன.
if vec.len() != N { return None; }
பைட்டுகளின் எண்ணிக்கை தவறாக இருந்தால், அது ஒரு தோல்வியாகும், மேலும் நாம் None-ஐத் திருப்பி அனுப்புகிறோம்.
// try_into ஆனது vec ஐ உட்கொண்டு [u8; N] ஐ உருவாக்க முயற்சிக்கிறது
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) ஒரு மதிப்பை மற்றொரு வகையாக மாற்றுகிறது, எடுத்துக்காட்டாக, ஒரு வெக்டரை அணியாக மாற்றுகிறது.
Some(array)
}
ஒரு செயல்பாட்டின் முடிவில் ஒரு மதிப்பைத் திருப்பி அனுப்பும்போது return (opens in a new tab) முக்கியச் சொல்லைப் பயன்படுத்த Rust உங்களைக் கட்டாயப்படுத்துவதில்லை.
#[wasm_bindgen]
pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option<String> {
இந்தச் செயல்பாடு ஒரு பொது மெட்டா-முகவரியைப் பெறுகிறது, இதில் Vpub மற்றும் Kpub ஆகிய இரண்டும் அடங்கும். இது மறைமுக முகவரி, வெளியிட வேண்டிய பொது விசை (Rpub) மற்றும் வெளியிடப்பட்ட முகவரிகளில் எது ஆலிஸுக்குச் சொந்தமானது என்பதை அடையாளம் காண்பதை வேகப்படுத்தும் ஒரு-பைட் ஸ்கேன் மதிப்பையும் திருப்பி அனுப்புகிறது.
ஸ்கேன் மதிப்பு என்பது பகிரப்பட்ட ரகசியத்தின் (S = GRprivVpriv) ஒரு பகுதியாகும். இந்த மதிப்பு ஆலிஸுக்குக் கிடைக்கிறது, மேலும் f(Kpub+G*hash(S)) வெளியிடப்பட்ட முகவரிக்குச் சமமாக உள்ளதா என்பதைச் சரிபார்ப்பதை விட இதைச் சரிபார்ப்பது மிகவும் வேகமானது.
let (address, r_pub, scan) =
generate_stealth_address(&str_to_array::<66>(stealth_address)?);
நாம் நிரலகத்தின் generate_stealth_address (opens in a new tab)-ஐப் பயன்படுத்துகிறோம்.
format!("{{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}}",
encode(address),
encode(r_pub),
encode(&[scan])
).into()
}
JSON-குறியிடப்பட்ட வெளியீட்டுச் சரத்தைத் தயாரிக்கவும்.
#[wasm_bindgen]
pub fn wasm_compute_stealth_key(
address: &str,
bill_pub_key: &str,
view_private_key: &str,
spend_private_key: &str
) -> Option<String> {
.
.
.
}
முகவரியிலிருந்து பணத்தை எடுப்பதற்கான தனிப்பட்ட திறவுகோலை (Rpriv) கணக்கிட, இந்தச் செயல்பாடு நிரலகத்தின் compute_stealth_key (opens in a new tab)-ஐப் பயன்படுத்துகிறது. இந்தக் கணக்கீட்டிற்கு இந்த மதிப்புகள் தேவை:
- முகவரி (Address=f(Ppub))
- பில் உருவாக்கிய பொது விசை (Rpub)
- பார்க்கும் தனிப்பட்ட திறவுகோல் (Vpriv)
- செலவழிக்கும் தனிப்பட்ட திறவுகோல் (Kpriv)
#[wasm_bindgen(start)]
WASM குறியீடு துவக்கப்படும்போது செயல்பாடு செயல்படுத்தப்படும் என்பதை #[wasm_bindgen(start)] (opens in a new tab) குறிப்பிடுகிறது.
pub fn main() {
console_error_panic_hook::set_once();
}
பீதி வெளியீடு (panic output) JavaScript கன்சோலுக்கு அனுப்பப்பட வேண்டும் என்பதை இந்தக் குறியீடு குறிப்பிடுகிறது. இது செயல்படுவதைப் பார்க்க, பயன்பாட்டைப் பயன்படுத்தி பில்லுக்குத் தவறான மெட்டா-முகவரியைக் கொடுங்கள் (ஒரு ஹெக்ஸாடெசிமல் இலக்கத்தை மட்டும் மாற்றவும்). JavaScript கன்சோலில் இந்தப் பிழையை நீங்கள் காண்பீர்கள்:
rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9:
assertion `left == right` failed
left: 0
right: 1
அதைத் தொடர்ந்து ஒரு ஸ்டாக் ட்ரேஸ் (stack trace) இருக்கும். பின்னர் பில்லுக்குச் சரியான மெட்டா-முகவரியைக் கொடுங்கள், மேலும் ஆலிஸுக்குத் தவறான முகவரி அல்லது தவறான பொது விசையைக் கொடுங்கள். நீங்கள் இந்தப் பிழையைக் காண்பீர்கள்:
rust_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:
keys 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) கொண்டுள்ளது.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import wasm from "vite-plugin-wasm";
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), wasm()],
})
நமக்கு இரண்டு Vite செருகுநிரல்கள் (plugins) தேவை: react (opens in a new tab) மற்றும் wasm (opens in a new tab).
App.jsx
இந்தக் கோப்பு பயன்பாட்டின் முக்கியக் கூறாகும். இது இரண்டு கூறுகளை உள்ளடக்கிய ஒரு கொள்கலன் (container): Alice மற்றும் Bill, அந்தப் பயனர்களுக்கான பயனர் இடைமுகங்கள். WASM-க்குத் தொடர்புடைய பகுதி துவக்கக் குறியீடாகும்.
import 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 கோப்பின் இயல்புநிலை ஏற்றுமதி (default export) என்பது WASM-ஐத் துவக்க இயங்க வேண்டிய குறியீடாகும்.
function App() {
.
.
.
useEffect(() => {
const loadWasm = async () => {
try {
await init();
setWasmReady(true)
} catch (err) {
console.error('Error loading wasm:', err)
alert("Wasm error: " + err)
}
}
loadWasm()
}, []
)
நிலை மாறிகள் (state variables) மாறும்போது செயல்படுத்தப்படும் ஒரு செயல்பாட்டைக் குறிப்பிட useEffect ஹூக் (hook) (opens in a new tab) உங்களை அனுமதிக்கிறது. இங்கே, நிலை மாறிகளின் பட்டியல் காலியாக உள்ளது ([]), எனவே பக்கம் ஏற்றப்படும்போது இந்தச் செயல்பாடு ஒரு முறை மட்டுமே செயல்படுத்தப்படும்.
எஃபெக்ட் (effect) செயல்பாடு உடனடியாகத் திரும்ப வேண்டும். WASM init போன்ற ஒத்திசைவற்ற (asynchronous) குறியீட்டைப் பயன்படுத்த (.wasm கோப்பை ஏற்ற வேண்டும், எனவே நேரம் எடுக்கும்) நாம் ஒரு உள் async (opens in a new tab) செயல்பாட்டை வரையறுத்து, அதை await இல்லாமல் இயக்குகிறோம்.
Bill.jsx
இது பில்லுக்கான பயனர் இடைமுகம். இது ஆலிஸ் வழங்கிய மறைமுக மெட்டா-முகவரியின் அடிப்படையில் ஒரு முகவரியை உருவாக்கும் ஒற்றைச் செயலைக் கொண்டுள்ளது.
import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js'
இயல்புநிலை ஏற்றுமதிக்குக் கூடுதலாக, wasm-pack உருவாக்கிய JavaScript குறியீடு WASM குறியீட்டில் உள்ள ஒவ்வொரு செயல்பாட்டிற்கும் ஒரு செயல்பாட்டை ஏற்றுமதி செய்கிறது.
<button onClick={() => {
setPublicAddress(JSON.parse(wasm_generate_stealth_address(stealthMetaAddress)))
}}>
WASM செயல்பாடுகளை அழைக்க, wasm-pack உருவாக்கிய JavaScript கோப்பால் ஏற்றுமதி செய்யப்பட்ட செயல்பாட்டை நாம் அழைக்கிறோம்.
Alice.jsx
Alice.jsx-இல் உள்ள குறியீடு ஒத்திருக்கிறது, ஆனால் ஆலிஸுக்கு இரண்டு செயல்கள் உள்ளன:
- ஒரு மெட்டா-முகவரியை உருவாக்குதல்
- பில் வெளியிட்ட முகவரிக்கான தனிப்பட்ட திறவுகோலைப் பெறுதல்
முடிவுரை
மறைமுக முகவரிகள் சஞ்சீவி அல்ல; அவை சரியாகப் பயன்படுத்தப்பட வேண்டும். ஆனால் சரியாகப் பயன்படுத்தப்படும்போது, அவை பொதுத் தொகுதிச்சங்கிலியில் தனியுரிமையைச் செயல்படுத்த முடியும்.