01 जनवरी 2026
nullprogram.com/blog/2026/01/01/
(लेखक वर्तमान में संयुक्त राज्य अमेरिका में रोजगार के अवसरों के लिए खुला है।)
कुछ जटिलता स्तर से ऊपर का सॉफ़्टवेयर एक विस्तार भाषा को स्पोर्ट करता है, जो स्वयं एक प्रकार का सॉफ़्टवेयर प्लेटफ़ॉर्म बन जाता है। लुआ इस भूमिका को अच्छी तरह से निभाता है, और निश्चित रूप से वेब प्रौद्योगिकियों के लिए जावास्क्रिप्ट है। WebAssembly इसे सामान्यीकृत करता है, और कोई भी Wasm-लक्ष्यीकरण प्रोग्रामिंग भाषा एक Wasm-होस्टिंग एप्लिकेशन का विस्तार कर सकती है। इसमें टेक्स्ट फ़ाइल में स्क्रिप्ट की आपूर्ति करने की तुलना में अधिक घर्षण है, लेकिन एक्सटेंशन लेखक अपनी पसंद की भाषा में लिख सकते हैं, और एक सामान्य एक्सटेंशन भाषा के लिए आम तौर पर उपलब्ध की तुलना में अधिक परिष्कृत विकास टूल – डिबगिंग, परीक्षण इत्यादि का उपयोग कर सकते हैं। पाइथॉन को पारंपरिक रूप से C इंटरफ़ेस के पीछे मूल कोड के माध्यम से विस्तारित किया जाता है, लेकिन हाल ही में पाइथॉन को वासम के साथ विस्तारित करना व्यावहारिक हो गया है। इसका मतलब है कि हम पायथन लाइब्रेरी के अंदर एक आर्किटेक्चर-स्वतंत्र वासम ब्लॉब भेज सकते हैं, और होस्ट सिस्टम पर देशी टूलचेन की आवश्यकता के बिना इसका उपयोग कर सकते हैं। आइए दो अलग-अलग उपयोग के मामलों और उनके नुकसानों पर चर्चा करें।
आम तौर पर हम बाहरी इंटरफ़ेस तक पहुंचने के लिए पायथन का विस्तार करेंगे, जिसे पायथन अपने आप एक्सेस नहीं कर सकता है। वासम एक सैंडबॉक्स में चलता है जिसकी बाहरी दुनिया तक कोई पहुंच नहीं है, इसलिए यह स्पष्ट रूप से उस मामले के लिए उपयोगी नहीं है। एक्सटेंशन पाइथॉन को अधिक गति भी प्रदान कर सकते हैं, जो वासम के मुख्य विक्रय बिंदुओं में से एक है। हम एक्सेस के लिए वास्म का भी उपयोग कर सकते हैं एम्बेड करने योग्य क्षमताएँ
एक अलग प्रोग्रामिंग भाषा में लिखा गया है जिसके लिए बाहरी पहुंच की आवश्यकता नहीं है।
पसंदीदा गैर-WASI Wasm रनटाइम के लिए वलोडिमिर शिमांस्की का wasm3 है। यह बिल्कुल पुराना सी है और इसमें एंबेड करने के लिए बहुत अनुकूल है, जैसे कि, SQLite। प्रदर्शन मध्यम है, हालाँकि wasm3 पर चलने वाला C प्रोग्राम अभी भी समकक्ष पायथन प्रोग्राम की तुलना में काफी तेज़ है। इसमें पायथन बाइंडिंग, pywasm3 है, लेकिन इसे केवल सोर्स कोड फॉर्म में वितरित किया गया है। यानी, pywasm3 का उपयोग करने के लिए होस्ट मशीन में C टूलचेन होना चाहिए, जो यहां मेरे उद्देश्यों को विफल करता है। यदि कोई सी टूलचेन है, तो मैं वास्म के माध्यम से जाने के बजाय बस उसका उपयोग कर सकता हूं।
इस आलेख में उपयोग के मामलों के लिए, सबसे अच्छा विकल्प wasmtime-py है। वितरण में x86-64 और ARM64 पर विंडोज़, मैकओएस और लिनक्स के लिए बायनेरिज़ शामिल हैं, जो लगभग सभी पायथन इंस्टॉलेशन को कवर करता है। मेजबानों को पाइथॉन दुभाषिया, किसी देशी टूलचेन से अधिक कुछ नहीं चाहिए। यह लगभग उतना ही अच्छा है जितना कि वासम को पायथन में ही बनाया गया है। मेरे परीक्षणों में यह wasm3 से 3x-10x तेज़ है, इसलिए मेरे पहले उपयोग के मामले में स्थिति और भी बेहतर है। समस्या यह है कि वर्तमान में इसका वजन ~18MiB (स्थापित) है, और भविष्य में संभवतः यह पायथन इंटरप्रेटर को ही टक्कर देगा। एपीआई भी मासिक आधार पर टूट जाती है, इसलिए आप अपग्रेड ट्रेडमिल के लिए साइन अप कर रहे हैं, ऐसा न हो कि आपका अपना प्रोग्राम कुछ वर्षों के बाद बिट्रोट में नष्ट हो जाए। यह लेख संस्करण 40 के बारे में है.
उपयोग के उदाहरण और गोचर
आधिकारिक उदाहरण कुछ भी गैर-तुच्छ या दिलचस्प नहीं करते हैं, और इसलिए चीजों को समझने के लिए मुझे दस्तावेज़ीकरण का अध्ययन करना पड़ा, जो कई संकेत नहीं देता है। मूल सेटअप इस तरह दिखता है:
import functools
import wasmtime
store = wasmtime.Store()
module = wasmtime.Module.from_file(store.engine, "example.wasm")
instance = wasmtime.Instance(store, module, ())
exports = instance.exports(store)
memory = exports["memory"].get_buffer_ptr(store)
func1 = functools.partial(exports["func1"], store)
func2 = functools.partial(exports["func2"], store)
func3 = functools.partial(exports["func3"], store)
स्टोर एक आवंटन क्षेत्र है जहाँ से हम सभी वास ऑब्जेक्ट आवंटित करते हैं। संपूर्ण भंडार को त्यागने के अलावा व्यक्तिगत वस्तुओं को मुक्त करना संभव नहीं है। काफी समझदार, ईमानदारी से। क्या है? नहीं समझदार यह है कि मुझे कितनी बार खुद को दोहराना पड़ता है, स्टोर का उपयोग करने के लिए उसे हर वस्तु में वापस डालना पड़ता है। ये ऑब्जेक्ट बिल्कुल एक ही स्टोर से जुड़े हैं और इन्हें अलग-अलग स्टोर के साथ इस्तेमाल नहीं किया जा सकता है। गलत स्टोर का उपयोग करें और यह घबरा जाता है: यह पहले से ही आंतरिक रूप से नज़र रख रहा है! मुझे समझ नहीं आता कि इंटरफ़ेस इस तरह क्यों काम करता है। इसलिए चीजों को सरल बनाने के लिए, मैं इसका उपयोग करता हूं functools.partial बाँधने के लिए store पैरामीटर और इसलिए मुझे अपेक्षित इंटरफ़ेस मिलता है।
get_buffer_ptr ऑब्जेक्ट एक बफर प्रोटोकॉल ऑब्जेक्ट है, और यदि आप बाइट्स के अलावा कुछ भी ले जा रहे हैं तो संभवतः आप मेमोरी तक पहुंचने के लिए इसका उपयोग करना चाहते हैं। इस ऑब्जेक्ट के लिए सामान्य चेतावनियाँ लागू होती हैं: यदि आप मेमोरी का आकार बदलते हैं तो आप संभवतः एक ताज़ा बफ़र ऑब्जेक्ट लेना चाहेंगे। बाइट्स के लिए (जैसे बफ़र्स और स्ट्रिंग्स) मैं इसे पसंद करता हूँ read और write तरीके.
क्योंकि मल्टी-वैल्यू अभी भी वासम पारिस्थितिकी तंत्र में प्रायोगिक स्थिति में है, आप संभवतः वास्म के साथ संरचनाओं को पारित नहीं करेंगे। स्केलर से अधिक जटिल किसी भी चीज़ के लिए वासम रैखिक मेमोरी के अंदर और बाहर पॉइंटर्स और डेटा की प्रतिलिपि बनाने की आवश्यकता होगी। इसमें सामान्य जाल शामिल है जो लगभग सभी को पकड़ता है: वास्म इंटरफेस पॉइंटर्स और पूर्णांकों के बीच कोई अंतर नहीं करता है, और वास्म रनटाइम आमतौर पर सभी पूर्णांकों को हस्ताक्षरित के रूप में व्याख्या करता है। इसका क्या मतलब है जब तक आप कार्रवाई नहीं करते, आपके पॉइंटर्स पर हस्ताक्षर किए जाते हैं. पते 0 से शुरू होते हैं, इसलिए यह बुरी, बुरी खबर है।
malloc = functools.partial(exports["func1"], store)
hello = b"hello"
pointer = malloc(len(hello))
assert pointer
memory = exports["memory"].write(store, hello, pointer) # WRONG!
मामले को बदतर बनाने के लिए, wasmtime-py ने अपना फ़ुटगन जोड़ा: द read और
write विधियाँ अंत से कार्य करने वाले नकारात्मक सूचकांकों के संदिग्ध पायथन सम्मेलन को अपनाती हैं। अगर malloc मेमोरी के ऊपरी आधे हिस्से में एक पॉइंटर लौटाता है, नकारात्मक पॉइंटर सीमा जांच को अंदर से पार कर जाएगा
write क्योंकि नकारात्मक वैध है, तो चुपचाप गलत पते पर स्टोर करें! दोहा!
मुझे आश्चर्य हुआ कि यह त्रुटि कितनी सामान्य है, इसलिए मैंने ऑनलाइन खोज की। मैं सैंडबॉक्स वाले पीडीएफ रीडर में जंगली में केवल एक गैर-तुच्छ wasmtime-py उपयोग पा सका। जैसा कि मेरी अपेक्षा थी, यह नकारात्मक सूचक जाल में फंस जाता है। इतना ही नहीं, यह पायथन की मेमोरी स्पेस में एक बफर ओवरफ़्लो है:
buf_ptr = malloc(store, len(pdf_data))
mem_data = memory.data_ptr(store)
for i, byte in enumerate(pdf_data):
mem_data[buf_ptr + i] = byte
data_ptr विधि एक गैर-सीमा-जाँचित कच्चा माल लौटाती है ctypes सूचक, तो यह वास्तव में एक दोहरी गलती है। सबसे पहले, अगर उसे सैंडबॉक्सिंग की जरा भी परवाह है तो उसे वासम से आने वाले संकेतों पर भरोसा नहीं करना चाहिए। दूसरा संभावित नकारात्मक सूचक है, जो इस मामले में वासम मेमोरी के बाहर और पायथन की मेमोरी में लिखेगा, उम्मीद है कि सेग-फॉल्टिंग।
किसी को क्या करना है? वासम से निकलने वाले प्रत्येक सूचक को छोटा किया जाना चाहिए
मास्क के साथ:
pointer = malloc(...) & 0xffffffff # correct for wasm32!
यह परिणाम को अहस्ताक्षरित के रूप में व्याख्या करता है। 64-बिट वासम को 64-बिट मास्क की आवश्यकता होती है, हालांकि व्यवहार में आपको 64-बिट वास्म से कभी भी वैध नकारात्मक सूचक नहीं मिलेगा। यह नियम जावास्क्रिप्ट पर भी लागू होता है, जहां मुहावरा है:
let pointer = malloc(...) >>> 0
वास्म रनटाइम मदद नहीं कर सकता – उनमें आवश्यक जानकारी का अभाव है – और यह शायद वासम के डिजाइन में एक बुनियादी दोष है। एक बार जब आपको इसके बारे में पता चल जाता है तो आप यह गलती हर जगह होते हुए देखते हैं।
अब जब आपके पास एक उचित पता है, तो आप इसे मेमोरी के बफर प्रोटोकॉल दृश्य पर लागू कर सकते हैं। यदि आप NumPy का उपयोग कर रहे हैं तो इस मेमोरी को NumPy प्रकारों में लपेटकर इसके साथ इंटरैक्ट करने के कई तरीके हैं, हालाँकि केवल तभी जब आप एक छोटे एंडियन होस्ट पर हों। (यदि आप एक बड़ी एंडियन मशीन पर हैं, तो वैसे भी वास्म चलाना छोड़ दें।) मेरे मन में जो पहला उपयोग मामला है, उसमें आम तौर पर सादे पायथन मानों को अंदर और बाहर कॉपी करना शामिल है। struct पैकेज यहाँ काफी उपयोगी है:
vec2 = malloc(...) & 0xffffffff
memory = exports["memory"].get_buffer_ptr(store)
struct.pack_into(", memory, vec2, x, y)
यह जावास्क्रिप्ट के समान भूमिका भरता है DataView. यदि आप बहुत सारी संख्याएँ कॉपी कर रहे हैं, तो CPython के साथ लूप का उपयोग करने के बजाय एक कस्टम प्रारूप स्ट्रिंग बनाना तेज़ है:
nums: list[int] = ...
struct.pack_into(f"<{len(nums)}i", memory, buf, *nums)
संरचनाओं को वापस कॉपी करने के लिए, उपयोग करें struct.unpack_from. यदि आप तार हिला रहे हैं, तो आपको इसकी आवश्यकता होगी .encode() और .decode() से और में कनवर्ट करने के लिए
bytesजो कि उपयुक्त हैं read और write.
वास्तविक वास्म कार्यक्रमों के अभ्यास में आप मेमोरी का अनुरोध करने के लिए बाहर से “अतिथि” आवंटनकर्ता के साथ बातचीत करने जा रहे हैं, जिसमें आप किसी फ़ंक्शन के लिए इनपुट कॉपी करते हैं। मेरे उदाहरणों में मैंने उपयोग किया है malloc क्योंकि इसके लिए किसी विस्तार की आवश्यकता नहीं है, लेकिन हमेशा की तरह एक बम्प एलोकेटर इसे बहुत बेहतर तरीके से हल करता है, खासकर इसलिए क्योंकि इसमें वासम प्रोग्राम के अंदर पूरे सामान्य प्रयोजन एलोकेटर को भरने की आवश्यकता नहीं होती है। एक वैश्विक क्षेत्र रखें – कोई अन्य थ्रेड उस वासम उदाहरण को साझा नहीं करेगा – “होस्ट” में मेमोरी प्रबंधन के लिए किसी भी चिंता के बिना आवश्यकतानुसार आवंटन का एक समूह तेजी से फायर करें, फ़ंक्शन को कॉल करें, जो उस क्षेत्र से परिणाम आवंटित कर सकता है, फिर क्षेत्र को साफ करने के लिए रीसेट करें। संक्षेप में मूल्यों को अंदर और बाहर भेजने के लिए एक स्टैक।
WebAssembly तेज़ Python जितना
मान लीजिए कि हमने अपने पायथन प्रोग्राम में शुद्ध पायथन फ़ंक्शन में एक कम्प्यूटेशनल हॉट स्पॉट देखा (उदाहरण के लिए किसी एक्सटेंशन को कॉल नहीं करना)। इस फ़ंक्शन को अनुकूलित करना बुद्धिमानी होगी. अपने प्रयोगों के आधार पर यदि मैं उस फ़ंक्शन को C में फिर से कार्यान्वित करता हूं, इसे Wasm में संकलित करता हूं, फिर मूल फ़ंक्शन के स्थान पर उस बिट Wasm को चलाता हूं, तो मैं लगभग 10x स्पीड-अप की उम्मीद कर सकता हूं। सामान्य तौर पर सी, पायथन की तुलना में 100 गुना अधिक तेज़ है, और वास्म के साथ इंटरफेसिंग का ओवरहेड – अंदर और बाहर सामान की प्रतिलिपि बनाना, आदि – अधिक हो सकता है, लेकिन इतना अधिक नहीं कि लाभदायक न हो। यदि मैं इंटरफ़ेस बदल सकता हूं तो इसमें और सुधार होता है, उदाहरण के लिए कॉलर्स को बफर प्रोटोकॉल का उपयोग करने की आवश्यकता होती है।
wasmtime-py के लिए धन्यवाद, मैं वितरण बायनेरिज़ बनाने के लिए क्रॉस-कंपाइलर्स के साथ परेशानी के बिना इस बदलाव को पेश कर सकता हूं, न ही लक्ष्य पर टूलचेन की आवश्यकता है, बस एक भारी पायथन पैकेज। शायद इसके लायक हो.
मेरा मुख्य प्रायोगिक बेंचमार्क “टू सम” समस्या के मेरे समाधान पर एक भिन्नता है, जिसे मैंने मूल रूप से जावास्क्रिप्ट के लिए लिखा था, फिर इसे pywasm3 और बाद में wasmtime-py तक बढ़ाया। यह सरल है, काफी दिलचस्प है, और मेरे मन में जो वासम ड्रॉप-इन है, उसका प्रतिनिधि है। इसका इंटरफ़ेस समान है, लेकिन इसे वास्म के साथ कार्यान्वित करता है।
# Original Pythonic interface
def twosum(nums: list[int], target: int) -> tuple[int, int] | None:
...
# Stateful Wasm interface
class TwoSumWasm():
def __init__(self):
store = wasmtime.Store()
module = wasmtime.Module.from_file(store.engine, ...)
instance = wasmtime.Instance(store, module, ())
...
def twosum(self, nums, target):
# ... use wasm instance ...
इसमें वासम उदाहरण के साथ कुछ स्थिति है। यदि आप इसे वैश्विक बनाकर छिपाते हैं तो आपको इसके चारों ओर अपने थ्रेड को सिंक्रनाइज़ करने की आवश्यकता होगी। एक बहु-थ्रेडेड प्रोग्राम में शायद ये आलसी ढंग से निर्मित थ्रेड लोकल होंगे। मुझे अभी तक इसे हल नहीं करना पड़ा है।
हालाँकि, wasmtime “स्टोर” की कमजोरी वास्तव में दिखती है: ध्यान दें कि एक स्टोर में संकलन और इंस्टेंटेशन एक साथ कैसे बंधे हैं? मैं एक बार संकलित नहीं कर सकता और फिर तुरंत डिस्पोजेबल इंस्टेंसेस नहीं बना सकता, उदाहरण के लिए WASI प्रोग्राम के प्रत्येक रन के लिए आवश्यक। प्रत्येक उदाहरण स्थायी रूप से संकलन भंडार का विस्तार करता है। व्यवहार में हमें प्रत्येक डिस्पोजेबल इंस्टेंस के लिए वासम प्रोग्राम को व्यर्थ में पुन: संकलित करना होगा। दिखावे के बावजूद, संकलन और इन्स्टेन्शियेशन वास्तव में अलग-अलग चरण नहीं हैं, क्योंकि वे जावास्क्रिप्ट के वासम एपीआई में हैं। wasmtime.Instance एक स्टोर को अपने पहले तर्क के रूप में स्वीकार करता है, सुझाना इन्स्टेन्शियेशन के लिए एक अलग स्टोर का उपयोग। इससे यह समस्या हल हो जाएगी, लेकिन जब तक यह लिखा जा रहा है अवश्य मॉड्यूल को संकलित करने के लिए उपयोग किया जाने वाला वही स्टोर हो। यह कुछ वास्तविक उपयोग के मामलों, विशेषकर WASI के लिए एक घातक दोष है।
एम्बेडेड क्षमताओं के रूप में WebAssembly
लूप वैलेंट की मोनोसाइफ़र एक अद्भुत क्रिप्टोग्राफी लाइब्रेरी है। दुबला, कुशल और एम्बेडिंग-अनुकूल, इतना कि इसे एकीकृत रूप में वितरित किया जाता है। इसके लिए किसी libc या रनटाइम की आवश्यकता नहीं है, इसलिए हम इसे लगभग किसी भी क्लैंग टूलचेन के साथ सीधे वास्म में संकलित कर सकते हैं:
$ clang --target=wasm32 -nostdlib -O2 -Wl,--no-entry -Wl,--export-all
-o monocypher.wasm monocypher.c
यह “वास्म-अवेयर” नहीं है इसलिए मुझे इसकी आवश्यकता है --export-all इंटरफ़ेस को उजागर करने के लिए. यह प्रफुल्लित है क्योंकि, एकल अनुवाद इकाई के रूप में, बाहरी लिंकेज वाली कोई भी चीज़ इंटरफ़ेस है। हालाँकि याद है कि मैंने अतिथि आवंटनकर्ता के साथ बातचीत के बारे में क्या कहा था? इसका कोई आवंटनकर्ता नहीं है, न ही होना चाहिए। इस रूप में यह इतना उपयोगी नहीं है क्योंकि हमें मेमोरी को बाहर से प्रबंधित करने की आवश्यकता होगी। करने योग्य, लेकिन एक ही अनुवाद इकाई पर टिके रहकर, कुछ और फ़ंक्शन जोड़कर इसे सुधारना आसान है:
#include "monocypher.c"
extern char __heap_base[];
static char *heap_used;
static char *heap_high;
void *bump_alloc(ptrdiff_t size)
{
// ...
}
void bump_reset()
{
ptrdiff_t len = heap_used - __heap_base;
__builtin_memset(__heap_base, 0, len); // wipe keys, etc.
heap_used = __heap_base;
}
मैंने चर्चा की है __heap_base पहले, जो एबीआई का हिस्सा है। हम इस “स्टैक” पर कुंजियाँ, इनपुट आदि दबाएँगे, अपना क्रिप्टोग्राफी रूटीन चलाएँगे, परिणाम की प्रतिलिपि बनाएंगे, फिर बम्प एलोकेटर को रीसेट करेंगे, जो सभी संवेदनशील डेटा को मिटा देगा। अक्सर memset अपर्याप्त है – आम तौर पर यह शून्य-तब-मुक्त है, और कंपाइलर जीवनकाल को समाप्त होने के बारे में देखते हैं – लेकिन यहां कोई जीवनकाल समाप्त नहीं होता है, और इस “ढेर” मेमोरी को बाहरी रूप से देखने योग्य संग्रहीत किया जाता है जहां तक अमूर्त मशीन बता सकती है। (अन्यथा हम विश्वसनीय रूप से अपने परिणामों की प्रतिलिपि नहीं बना सकते!)
इस एपीआई में बहुत कुछ है, लेकिन मैं केवल AEAD इंटरफ़ेस को देखने जा रहा हूं। हम कुछ डेटा को एक एन्क्रिप्टेड बॉक्स में “लॉक” कर देते हैं, बाहर कोई भी अनएन्क्रिप्टेड लेबल लिखते हैं जो हम चाहते हैं। फिर बाद में हम बॉक्स को अनलॉक कर सकते हैं, जो हमारे लिए केवल तभी खुलेगा जब न तो बॉक्स की सामग्री और न ही लेबल के साथ कोई छेड़छाड़ की गई हो। यह कुछ ठोस एपीआई डिज़ाइन है:
void crypto_aead_lock(uint8_t *cipher_text,
uint8_t mac [16],
const uint8_t key [32],
const uint8_t nonce[24],
const uint8_t *ad, size_t ad_size,
const uint8_t *plain_text, size_t text_size);
int crypto_aead_unlock(uint8_t *plain_text,
const uint8_t mac [16],
const uint8_t key [32],
const uint8_t nonce[24],
const uint8_t *ad, size_t ad_size,
const uint8_t *cipher_text, size_t text_size);
वास्म को संकलित करके हम इस कार्यक्षमता को पायथन से लगभग उसी तरह एक्सेस कर सकते हैं जैसे यह शुद्ध पायथन था, और मोनोसिफर का उपयोग करके अन्य प्रणालियों के साथ बातचीत कर सकते हैं।
चूँकि मोनोसाइफ़र अपने आप बाहरी दुनिया के साथ इंटरैक्ट नहीं करता है, यह उन नॉन्स और कुंजियों को बनाने के लिए अपने सिस्टम के CSPRNG का उपयोग करने के लिए कॉल करने वालों पर निर्भर करता है, जो हम इसका उपयोग करके करेंगे। secrets अंतर्निर्मित पैकेज:
class Monocypher:
def __init__(self):
...
self._read = functools.partial(memory.read, store)
self._write = functools.partial(memory.write, store)
self.__alloc = functools.partial(exports["bump_alloc"], store)
self._reset = functools.partial(exports["bump_reset"], store)
self._lock = functools.partial(exports["crypto_aead_lock"], store)
self._unlock = functools.partial(exports["crypto_aead_unlock"], store)
self._csprng = secrets.SystemRandom()
def _alloc(self, n):
return self.__alloc(n) & 0xffffffff
def generate_key(self):
return self._csprng.randbytes(32)
def generate_nonce(self):
return self._csprng.randbytes(24)
...
एक ठोस आधार के साथ, जो कुछ भी होता है वह आसानी से हो जाता है। ए finally
गारंटी रहस्य हमेशा वास मेमोरी से हटा दिए जाते हैं, और बाकी केवल बाइट्स की प्रतिलिपि बनाने के बारे में है:
def aead_lock(self, text, key, ad = b""):
assert len(key) == 32
try:
macptr = self._alloc(16)
keyptr = self._alloc(32)
nonceptr = self._alloc(24)
adptr = self._alloc(len(ad))
textptr = self._alloc(len(text))
self._write(key, keyptr)
nonce = self.generate_nonce()
self._write(nonce, nonceptr)
self._write(ad, adptr)
self._write(text, textptr)
self._lock(
textptr,
macptr,
keyptr,
nonceptr,
adptr, len(ad),
textptr, len(text),
)
return (
self._read(macptr, macptr+16),
nonce,
self._read(textptr, textptr+len(text)),
)
finally:
self._reset()
और aead_unlock मूल रूप से रिवर्स में समान है, लेकिन यदि बॉक्स अनलॉक करने में विफल रहता है, तो संभवतः छेड़छाड़ के कारण फेंक देता है:
def aead_unlock(self, text, mac, key, nonce, ad = b""):
assert len(mac) == 16
assert len(key) == 32
assert len(nonce) == 24
try:
macptr = self._alloc(16)
keyptr = self._alloc(32)
nonceptr = self._alloc(24)
adptr = self._alloc(len(ad))
textptr = self._alloc(len(text))
self._write(mac, macptr)
self._write(key, keyptr)
self._write(nonce, nonceptr)
self._write(ad, adptr)
self._write(text, textptr)
if self._unlock(
textptr,
macptr,
keyptr,
nonceptr,
adptr, len(ad),
textptr, len(text),
):
raise ValueError("AEAD mismatch")
return self._read(textptr, textptr+len(text))
finally:
self._reset()
उपयोग:
mc = Monocypher()
key = mc.generate_key()
message = "Hello, world!"
mac, nonce, encrypted = mc.aead_lock(message.encode(), key)
संचारित mac, nonceऔर encrypted दूसरे पक्ष के लिए (या आपके भविष्य के लिए), जिसके पास पहले से ही है key:
decrypted = mc.aead_unlock(encrypted, mac, key, nonce)
खोजें मेरे स्क्रैच भंडार में संपूर्ण स्रोत.
हालाँकि मुझे wasmtime-py के बारे में कुछ आपत्तियां हैं, लेकिन यह मुझे रोमांचित करता है कि यह सब कितनी अच्छी तरह काम करता है। पिछले कुछ समय से यह मेरा हथौड़ा कील की तलाश में है।
<a href