پائڈراسن: میں نے سلاٹ اور بلاب کے ساتھ ASN.1 لائبریری کیسے لکھی۔

ASN.1۔ یہ ایک زبان کا ایک معیاری (ISO, ITU-T, GOST) ہے جو ساختی معلومات کو بیان کرتی ہے، نیز اس معلومات کو انکوڈنگ کرنے کے اصول۔ میرے لیے، ایک پروگرامر کے طور پر، یہ JSON، XML، XDR اور دیگر کے ساتھ ڈیٹا کو سیریلائز کرنے اور پیش کرنے کا ایک اور فارمیٹ ہے۔ یہ ہماری روزمرہ کی زندگی میں بہت عام ہے، اور بہت سے لوگ اس کا سامنا کرتے ہیں: سیلولر، ٹیلی فون، VoIP کمیونیکیشنز (UMTS, LTE, WiMAX, SS7, H.323) میں، نیٹ ورک پروٹوکول (LDAP، SNMP، Kerberos) میں، ہر چیز میں جو بینک کارڈز اور بایومیٹرک پاسپورٹ میں خفیہ نگاری (X.509، CMS، PKCS معیارات) اور بہت کچھ سے متعلق ہے۔

اس مضمون سے متعلق ہے۔ پائڈراسن: Python ASN.1 لائبریری کو خفیہ نگاری سے متعلق منصوبوں میں فعال طور پر استعمال کیا جاتا ہے۔ اٹلس.

پائڈراسن: میں نے سلاٹ اور بلاب کے ساتھ ASN.1 لائبریری کیسے لکھی۔
عام طور پر، ASN.1 خفیہ کاموں کے لیے تجویز کرنے کے قابل نہیں ہے: ASN.1 اور اس کے کوڈیکس پیچیدہ ہیں۔ اس کا مطلب یہ ہے کہ کوڈ آسان نہیں ہوگا، اور یہ ہمیشہ ایک اضافی حملہ کرنے والا ویکٹر ہوتا ہے۔ صرف دیکھو فہرست میں ASN.1 لائبریریوں میں کمزوریاں۔ بروس شنئیر اپنے میں خفیہ نگاری انجینئرنگ اس کی پیچیدگی کی وجہ سے اس معیار کو استعمال کرنے کے خلاف بھی مشورہ دیتے ہیں: "سب سے مشہور TLV انکوڈنگ ASN.1 ہے، لیکن یہ ناقابل یقین حد تک پیچیدہ ہے اور ہم اس سے کتراتے ہیں۔" لیکن، بدقسمتی سے، آج ہمارے پاس ہے عوامی کلیدی بنیادی ڈھانچہ جس میں وہ فعال طور پر استعمال ہوتے ہیں۔ X.509 سرٹیفکیٹ، CRL، OCSP، TSP، CMP پروٹوکول، CMC، پیغامات CMS، اور بہت سارے معیارات پی کے سی ایس. لہذا، اگر آپ خفیہ نگاری سے متعلق کچھ کر رہے ہیں تو آپ کو ASN.1 کے ساتھ کام کرنے کے قابل ہونا پڑے گا۔

ASN.1 کو مختلف طریقوں/کوڈیکس میں انکوڈ کیا جا سکتا ہے:

  • BER (انکوڈنگ کے بنیادی اصول)
  • CER (کیننیکل انکوڈنگ رولز)
  • DER (ممتاز انکوڈنگ قواعد)
  • جی ایس ای آر (عام سٹرنگ انکوڈنگ کے اصول)
  • JER (JSON انکوڈنگ کے اصول)
  • LWER (ہلکے وزن کے انکوڈنگ کے اصول)
  • او ای آر (آکٹیٹ انکوڈنگ رولز)
  • فی (پیکڈ انکوڈنگ رولز)
  • SER (مخصوص انکوڈنگ رولز کو سگنل کرنا)
  • شاگرد (XML انکوڈنگ رولز)

اور بہت سے دوسرے. لیکن کرپٹوگرافک کاموں میں، عملی طور پر، دو استعمال ہوتے ہیں: BER اور DER۔ یہاں تک کہ دستخط شدہ XML دستاویزات میں (XMLDSig, XAdES) ابھی بھی Base64-encoded ASN.1 DER آبجیکٹ موجود ہوں گے، جیسا کہ JSON پر مبنی پروٹوکول میں ہے۔ ACME آئیے انکرپٹ سے۔ آپ مضامین اور کتابوں میں ان تمام کوڈیکس اور BER/CER/DER کوڈنگ کے اصولوں کو بہتر طور پر سمجھ سکتے ہیں: آسان الفاظ میں ASN.1, ASN.1 — متضاد نظاموں کے درمیان مواصلت بذریعہ اولیور ڈوبیسن, ASN.1 پروفیسر جان لارماؤتھ کے ذریعہ مکمل.

BER ایک بائنری بائٹ پر مبنی ہے (مثال کے طور پر PER، سیلولر کمیونیکیشنز میں مقبول - بٹ اورینٹڈ) TLV فارمیٹ۔ ہر عنصر کو بطور انکوڈ کیا گیا ہے: ٹیگ (Tag)، انکوڈ کیے جانے والے عنصر کی قسم کی شناخت کرنا (انٹیجر، سٹرنگ، تاریخ، وغیرہ)، لمبائی (Length) مواد اور خود مواد (Value)۔ BER اختیاری طور پر آپ کو اجازت دیتا ہے کہ ایک خاص غیر معینہ طوالت کی قدر ترتیب دے کر اور اینڈ-آف-آکٹیٹس پیغام کو اینڈ-آف-آکٹیٹس کے نشان کے ساتھ ختم کر کے لمبائی کی قدر متعین نہ کریں۔ لمبائی کی انکوڈنگ کے علاوہ، BER میں ڈیٹا کی اقسام کو انکوڈ کرنے کے طریقے میں بہت زیادہ تغیرات ہیں، جیسے:

  • انٹیجر، آبجیکٹ شناخت کنندہ، بٹ سٹرنگ اور عنصر کی لمبائی کو عام نہیں کیا جا سکتا (کم سے کم شکل میں انکوڈ نہیں کیا گیا)؛
  • BOOLEAN کسی بھی غیر صفر مواد کے لیے درست ہے۔
  • BIT STRING میں "اضافی" صفر بٹس شامل ہو سکتے ہیں۔
  • BIT STRING، OCTET STRING اور تاریخ/وقت سمیت ان کی تمام اخذ کردہ سٹرنگ اقسام کو متغیر لمبائی کے حصوں میں تقسیم کیا جا سکتا ہے، جس کی لمبائی (de)انکوڈنگ کے وقت پہلے سے معلوم نہیں ہوتی ہے۔
  • UTCTtime/GeneralizedTime کے پاس ٹائم زون آفسیٹ اور سیکنڈ کے "اضافی" صفر حصوں کی وضاحت کرنے کے مختلف طریقے ہو سکتے ہیں۔
  • DEFAULT SEQUENCE اقدار کو انکوڈ کیا جا سکتا ہے یا نہیں؛
  • BIT STRING میں آخری بٹس کی نامزد اقدار کو اختیاری طور پر بغیر انکوڈ کیا جا سکتا ہے۔
  • SEQUENCE (OF)/SET (OF) میں عناصر کی کوئی بھی ترتیب ہو سکتی ہے۔

مندرجہ بالا سبھی کی وجہ سے، ڈیٹا کو انکوڈنگ کرنا تاکہ یہ اصل شکل سے مماثل ہو ہمیشہ ممکن نہیں ہوتا ہے۔ لہذا، قواعد کا ایک ذیلی سیٹ ایجاد کیا گیا: DER - صرف ایک درست انکوڈنگ طریقہ کو سختی سے ریگولیٹ کرنا، جو کہ کرپٹوگرافک کاموں کے لیے اہم ہے جہاں، مثال کے طور پر، ایک بٹ تبدیل کرنے سے دستخط یا چیکسم غلط ہو جائے گا۔ DER کا ایک اہم نقصان ہے: تمام عناصر کی طوالت کو انکوڈنگ کے وقت پہلے سے معلوم ہونا چاہیے، جو ڈیٹا کی سٹریم سیریلائزیشن کی اجازت نہیں دیتا ہے۔ CER کوڈیک میں یہ خرابی نہیں ہے، اسی طرح ڈیٹا کی غیر مبہم نمائندگی کی ضمانت دیتا ہے۔ بدقسمتی سے (یا یہ خوش قسمتی ہے کہ ہمارے پاس اس سے زیادہ پیچیدہ ڈیکوڈرز نہیں ہیں؟)، یہ مقبول نہیں ہوا۔ لہذا، عملی طور پر ہمیں BER اور DER انکوڈ شدہ ڈیٹا کے "مخلوط" استعمال کا سامنا کرنا پڑتا ہے۔ چونکہ CER اور DER دونوں BER کے ذیلی سیٹ ہیں، کوئی بھی BER ڈیکوڈر انہیں سنبھال سکتا ہے۔

pyasn1 کے ساتھ مسائل

کام پر ہم خفیہ نگاری سے متعلق بہت سے ازگر پروگرام لکھتے ہیں۔ اور کچھ سال پہلے مفت لائبریریوں کا عملی طور پر کوئی انتخاب نہیں تھا: یا تو یہ بہت کم درجے کی لائبریریاں ہیں جو آپ کو آسانی سے انکوڈ/ڈی کوڈ کرنے کی اجازت دیتی ہیں، مثال کے طور پر، ایک عدد اور ڈھانچہ ہیڈر، یا یہ لائبریری pyasn1. ہم اس پر کئی سال رہے اور پہلے تو ہم بہت خوش ہوئے، کیونکہ یہ آپ کو ASN.1 ڈھانچے کے ساتھ کام کرنے کی اجازت دیتا ہے جیسا کہ اعلیٰ سطحی اشیاء کے ساتھ: مثال کے طور پر، ایک ڈی کوڈ شدہ X.509 سرٹیفکیٹ آبجیکٹ آپ کو اس کے فیلڈز تک رسائی کی اجازت دیتا ہے۔ ڈکشنری انٹرفیس: سرٹیفکیٹ["tbsCertificate"] ["serialNumber"] ہمیں اس سرٹیفکیٹ کا سیریل نمبر دکھائے گا۔ اسی طرح، آپ پیچیدہ اشیاء کو فہرستوں، لغات کے طور پر کام کرکے "جمع" کرسکتے ہیں، اور پھر صرف pyasn1.codec.der.encoder.encode فنکشن کو کال کریں اور دستاویز کی سیریلائزڈ نمائندگی حاصل کریں۔

تاہم کوتاہیوں، مسائل اور حدود کا انکشاف ہوا۔ pyasn1 میں غلطیاں تھیں اور بدقسمتی سے اب بھی ہیں: لکھنے کے وقت، pyasn1 کی بنیادی اقسام میں سے ایک GeneralizedTime ہے، غلط طور پر ضابطہ کشائی اور انکوڈ شدہ۔

ہمارے پروجیکٹس میں، جگہ بچانے کے لیے، ہم اکثر صرف فائل پاتھ، آفسیٹ اور لمبائی کو اس چیز کے بائٹس میں اسٹور کرتے ہیں جس کا ہم حوالہ دینا چاہتے ہیں۔ مثال کے طور پر، ایک صوابدیدی دستخط شدہ فائل غالباً CMS SignedData ASN.1 ڈھانچے میں واقع ہوگی:

  0     [1,3,1018]  ContentInfo SEQUENCE
  4     [1,1,   9]   . contentType: ContentType OBJECT IDENTIFIER 1.2.840.113549.1.7.2 (id_signedData)
 19-4   [0,0,1003]   . content: [0] EXPLICIT [UNIV 16] ANY
 19     [1,3, 999]   . . DEFINED BY id_signedData: SignedData SEQUENCE
 23     [1,1,   1]   . . . version: CMSVersion INTEGER v3 (03)
 26     [1,1,  19]   . . . digestAlgorithms: DigestAlgorithmIdentifiers SET OF
                           [...]
 47     [1,3, 769]   . . . encapContentInfo: EncapsulatedContentInfo SEQUENCE
 51     [1,1,   8]   . . . . eContentType: ContentType OBJECT IDENTIFIER 1.3.6.1.5.5.7.12.2 (id_cct_PKIData)
 65-4   [1,3, 751]   . . . . eContent: [0] EXPLICIT OCTET STRING 751 bytes OPTIONAL

                 ТУТ СОДЕРЖИМОЕ ПОДПИСЫВАЕМОГО ФАЙЛА РАЗМЕРОМ 751 байт

820     [1,2, 199]   . . . signerInfos: SignerInfos SET OF
823     [1,2, 196]   . . . . 0: SignerInfo SEQUENCE
826     [1,1,   1]   . . . . . version: CMSVersion INTEGER v3 (03)
829     [0,0,  22]   . . . . . sid: SignerIdentifier CHOICE subjectKeyIdentifier
                               [...]
956     [1,1,  64]   . . . . . signature: SignatureValue OCTET STRING 64 bytes
                     . . . . . . C1:B3:88:BA:F8:92:1C:E6:3E:41:9B:E0:D3:E9:AF:D8
                     . . . . . . 47:4A:8A:9D:94:5D:56:6B:F0:C1:20:38:D2:72:22:12
                     . . . . . . 9F:76:46:F6:51:5F:9A:8D:BF:D7:A6:9B:FD:C5:DA:D2
                     . . . . . . F3:6B:00:14:A4:9D:D7:B5:E1:A6:86:44:86:A7:E8:C9

اور ہم اصل دستخط شدہ فائل کو آفسیٹ 65 بائٹس، 751 بائٹس لمبی پر حاصل کر سکتے ہیں۔ pyasn1 اس معلومات کو اپنی ڈی کوڈ شدہ اشیاء میں محفوظ نہیں کرتا ہے۔ نام نہاد TLVSeeker لکھا گیا تھا - ایک چھوٹی لائبریری جو آپ کو ٹیگز اور آبجیکٹ کی لمبائی کو ڈی کوڈ کرنے کی اجازت دیتی ہے، جس کے انٹرفیس میں ہم نے "اگلے ٹیگ پر جائیں"، "ٹیگ کے اندر جائیں" (SEQUENCE آبجیکٹ کے اندر جائیں) کا حکم دیا ہے۔ "اگلے ٹیگ پر جائیں"، "اپنا آفسیٹ اور اس چیز کی لمبائی بتائیں جہاں ہم ہیں۔" یہ ASN.1 DER- سیریلائزڈ ڈیٹا کے ذریعے ایک "دستی" واک تھا۔ لیکن اس طرح BER سیریلائزڈ ڈیٹا کے ساتھ کام کرنا ناممکن تھا، کیونکہ مثال کے طور پر، OCTET STRING بائٹ سٹرنگ کو کئی حصوں کی شکل میں انکوڈ کیا جا سکتا ہے۔

ہمارے pyasn1 کاموں کے لیے ایک اور خرابی ڈی کوڈ شدہ اشیاء سے یہ سمجھنے میں ناکامی ہے کہ آیا کوئی فیلڈ SEQUENCE میں موجود تھا یا نہیں۔ مثال کے طور پر، اگر ڈھانچہ Smth OPTIONAL فیلڈ کا ایک فیلڈ SEQUENCE پر مشتمل ہے، تو یہ آنے والے ڈیٹا (OPTIONAL) سے مکمل طور پر غائب ہوسکتا ہے، یا یہ موجود ہوسکتا ہے، لیکن صفر کی لمبائی (خالی فہرست) کا ہو۔ عام طور پر، اس کا تعین نہیں کیا جا سکتا. اور یہ موصول شدہ ڈیٹا کی درستگی کی سخت تصدیق کے لیے ضروری ہے۔ تصور کریں کہ کچھ سرٹیفیکیشن اتھارٹی ڈیٹا کے ساتھ ایک سرٹیفکیٹ جاری کرے گی جو ASN.1 اسکیموں کے نقطہ نظر سے "مکمل طور پر درست نہیں" ہے! مثال کے طور پر، سرٹیفیکیشن اتھارٹی "TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı" نے اپنے روٹ سرٹیفکیٹ میں قابل اجازت حد سے تجاوز کیا آر ایف سی 5280 موضوع کے اجزاء کی لمبائی کی حد - اسکیم کے مطابق اسے ایمانداری سے ڈی کوڈ نہیں کیا جاسکتا۔ DER کوڈیک کا تقاضا ہے کہ ایک فیلڈ جس کی قیمت ڈیفالٹ کے برابر ہے ٹرانسمیشن کے دوران انکوڈ نہ کی جائے - ایسی دستاویزات زندگی میں ہوتی ہیں، اور PyDERASN کے پہلے ورژن نے بھی جان بوجھ کر اس طرح کے غلط (DER نقطہ نظر سے) رویے کی اجازت دی تھی۔ پسماندہ مطابقت.

ایک اور حد آسانی سے یہ معلوم کرنے سے قاصر ہے کہ ساخت میں کسی خاص چیز کو کس شکل میں (BER/DER) انکوڈ کیا گیا تھا۔ مثال کے طور پر، CMS معیار کہتا ہے کہ پیغام BER-encoded ہے، لیکن signedAttrs فیلڈ، جس پر کرپٹوگرافک دستخط تیار ہوتا ہے، DER میں ہونا چاہیے۔ اگر ہم DER کے ساتھ ڈی کوڈ کرتے ہیں، تو ہم خود CMS کی پروسیسنگ میں ناکام ہو جائیں گے؛ اگر ہم BER کے ساتھ ڈی کوڈ کرتے ہیں، تو ہمیں نہیں معلوم ہوگا کہ دستخط شدہAttrs کس شکل میں تھا۔ نتیجے کے طور پر، TLVSeeker (جس کا pyasn1 میں کوئی اینالاگ نہیں ہے) کو ہر دستخط شدہAttrs فیلڈ کا مقام تلاش کرنا ہوگا، اور الگ الگ، اسے سیریلائزڈ نمائندگی سے باہر لے کر، اسے DER کے ساتھ ڈی کوڈ کرنا ہوگا۔

خود کار طریقے سے DEFINED BY کھیتوں پر کارروائی کرنے کی صلاحیت، جو کہ بہت عام ہے، ہمارے لیے بہت مطلوب تھی۔ ASN.1 ڈھانچے کو ڈی کوڈ کرنے کے بعد، ہمارے پاس بہت سے فیلڈز رہ سکتے ہیں جن پر ڈھانچہ فیلڈ میں مخصوص آبجیکٹ شناخت کنندہ کی بنیاد پر منتخب کردہ اسکیم کے مطابق مزید کارروائی کی جانی چاہیے۔ Python کوڈ میں، اس کا مطلب ہے if اور پھر کسی بھی فیلڈ کے لیے ڈیکوڈر کو کال کرنا۔

PyDERASN کا ظہور

اٹلس میں، ہم باقاعدگی سے پیچ بھیجتے ہیں جب ہمیں کچھ مسائل ملتے ہیں یا ہمارے استعمال کردہ مفت پروگراموں کو بہتر بناتے ہیں۔ ہم نے pyasn1 میں کئی بار بہتری جمع کروائی، لیکن pyasn1 کے کوڈ کو سمجھنا سب سے آسان نہیں ہے اور بعض اوقات غیر مطابقت پذیر API تبدیلیاں ہوتی ہیں جو ہمیں شکست دیتی ہیں۔ اس کے علاوہ، ہم جنریٹو ٹیسٹنگ کے ساتھ ٹیسٹ لکھنے کے عادی ہیں، جو pyasn1 میں نہیں تھا۔

ایک اچھے دن میں نے فیصلہ کیا کہ میرے پاس یہ کافی ہے اور اب وقت آگیا ہے کہ میں اپنی لائبریری کو __slot__s، آفسیٹس اور خوبصورتی سے دکھائے گئے بلاب کے ساتھ لکھنے کی کوشش کروں! صرف ایک ASN.1 کوڈیک بنانا کافی نہیں ہوگا - ہمیں اپنے تمام منحصر منصوبوں کو اس میں منتقل کرنے کی ضرورت ہے، اور یہ کوڈ کی لاکھوں لائنیں ہیں جو ASN.1 کے ڈھانچے کے ساتھ کام سے بھری ہوئی ہیں۔ یعنی، اس کی ضروریات میں سے ایک: موجودہ pyasn1 کوڈ کے ترجمہ میں آسانی۔ اپنی تمام چھٹیاں گزارنے کے بعد، میں نے یہ لائبریری لکھی اور تمام پروجیکٹس اس میں منتقل کر دیے۔ چونکہ ان کے پاس ٹیسٹ کے ساتھ تقریباً 100% کوریج ہے، اس کا مطلب ہے کہ لائبریری مکمل طور پر کام کر رہی تھی۔

PyDERASN، اسی طرح، تقریباً 100% ٹیسٹ کوریج رکھتا ہے۔ ایک عظیم لائبریری کے ساتھ جنریٹو ٹیسٹنگ کا استعمال کرتا ہے۔ پرختیارپنا. اس پر عمل بھی کیا گیا۔ مبہم py-afl- میں 32 ایٹمی مشینوں پر کھاتا ہوں۔ اس حقیقت کے باوجود کہ ہمارے پاس عملی طور پر کوئی Python2 کوڈ باقی نہیں ہے، PyDERASN اب بھی اس کے ساتھ مطابقت رکھتا ہے اور اس کی وجہ سے چھ لت اس کے علاوہ، اس کے خلاف ٹیسٹ کیا جاتا ہے ASN.1:2008 تعمیل ٹیسٹ سویٹ.

اس کے ساتھ کام کرنے کا اصول pyasn1 کی طرح ہے - اعلی درجے کی Python اشیاء کے ساتھ کام کرنا۔ ASN.1 اسکیموں کی تفصیل اسی طرح کی ہے۔

class TBSCertificate(Sequence):
    schema = (
        ("version", Version(expl=tag_ctxc(0), default="v1")),
        ("serialNumber", CertificateSerialNumber()),
        ("signature", AlgorithmIdentifier()),
        ("issuer", Name()),
        ("validity", Validity()),
        ("subject", Name()),
        ("subjectPublicKeyInfo", SubjectPublicKeyInfo()),
        ("issuerUniqueID", UniqueIdentifier(impl=tag_ctxp(1), optional=True)),
        ("subjectUniqueID", UniqueIdentifier(impl=tag_ctxp(2), optional=True)),
        ("extensions", Extensions(expl=tag_ctxc(3), optional=True)),
    )

تاہم، PyDERASN میں مضبوط ٹائپنگ کی کچھ جھلک ہے۔ pyasn1 میں، اگر کوئی فیلڈ CMSVersion(INTEGER) کی قسم کی تھی، تو اسے int یا INTEGER تفویض کیا جا سکتا ہے۔ PyDERASN کا سختی سے تقاضا ہے کہ تفویض کردہ آبجیکٹ بالکل CMSVersion ہو۔ Python3 کوڈ لکھنے کے علاوہ، ہم بھی استعمال کرتے ہیں۔ تشریحات ٹائپ کرنا، لہذا ہمارے فنکشنز میں def func(سیریل، مواد) جیسے غیر واضح دلائل نہیں ہوں گے، لیکن def func(سیریل: CertificateSerialNumber، مواد: EncapsulatedContentInfo)، اور PyDERASN ایسے کوڈ کو برقرار رکھنے میں مدد کرتا ہے۔

ایک ہی وقت میں، PyDERASN کے پاس اس ٹائپنگ کے لیے انتہائی آسان رعایتیں ہیں۔ pyasn1 نے SubjectKeyIdentifier().subtype(implicitTag=Tag(...)) فیلڈ کو SubjectKeyIdentifier() (ضروری IMPLICIT TAG کے بغیر) کو ایک آبجیکٹ تفویض کرنے کی اجازت نہیں دی اور صرف اس وجہ سے اشیاء کو کاپی کرنا اور دوبارہ بنانا ضروری تھا۔ تبدیل شدہ IMPLICIT/EXPLICIT ٹیگز۔ PyDERASN صرف بنیادی قسم کا سختی سے مشاہدہ کرتا ہے - یہ خود بخود ساخت کے پہلے سے موجود ASN.1 اسکیما سے ٹیگز کو بدل دے گا۔ یہ ایپلیکیشن کوڈ کو بہت آسان بناتا ہے۔

اگر ڈی کوڈنگ کے دوران کوئی خرابی واقع ہو جاتی ہے، تو pyasn1 میں یہ سمجھنا آسان نہیں ہے کہ یہ کہاں واقع ہوئی ہے۔ مثال کے طور پر، اوپر بیان کردہ ترکی سرٹیفکیٹ میں، ہمیں درج ذیل خرابی موصول ہوگی: UTF8String (tbsCertificate:issuer:rdnSequence:3:0:value:DEFINED BY 2.5.4.10:utf8String) (138 پر) غیر مطمئن حدیں: 1 ⇐ 77 ⇐ 64 ASN .1 ڈھانچہ لکھتے وقت لوگ غلطیاں کر سکتے ہیں، اور اس سے ایپلیکیشنز کو ڈیبگ کرنا یا دوسرے فریق کے کوڈ شدہ دستاویزات کے ساتھ مسائل کا پتہ لگانا آسان ہو جاتا ہے۔

PyDERASN کا پہلا ورژن BER انکوڈنگ کو سپورٹ نہیں کرتا تھا۔ یہ بہت بعد میں ظاہر ہوا اور اب بھی ٹائم زونز کے ساتھ UTCTime/GeneralizedTime کی پروسیسنگ کی حمایت نہیں کرتا ہے۔ یہ مستقبل میں آئے گا، کیونکہ پروجیکٹ بنیادی طور پر میرے فارغ وقت میں لکھا گیا ہے۔

اس کے علاوہ، پہلے ورژن میں DEFINED BY فیلڈز کے ساتھ کوئی کام نہیں تھا۔ چند ماہ بعد یہ موقع پیدا ہوا اور فعال طور پر استعمال ہونے لگا، جس سے ایپلیکیشن کوڈ کو نمایاں طور پر کم کیا گیا - ایک ضابطہ کشائی کی کارروائی میں پوری ساخت کو بہت گہرائی تک جدا کرنا ممکن تھا۔ ایسا کرنے کے لیے، اسکیما بتاتا ہے کہ کون سے فیلڈز کیا "تعریف" کرتے ہیں۔ مثال کے طور پر، CMS اسکیم کی تفصیل:

class ContentInfo(Sequence):
    schema = (
        ("contentType", ContentType(defines=((("content",), {
            id_authenticatedData: AuthenticatedData(),
            id_digestedData: DigestedData(),
            id_encryptedData: EncryptedData(),
            id_envelopedData: EnvelopedData(),
            id_signedData: SignedData(),
        }),))),
        ("content", Any(expl=tag_ctxc(0))),
    )

کہتا ہے کہ اگر contentType میں id_signedData ویلیو کے ساتھ OID ہے، تو پھر کنٹینٹ فیلڈ (اسی SEQUENCE میں واقع ہے) کو SignedData اسکیم کے مطابق ڈی کوڈ کیا جانا چاہیے۔ اتنے قوسین کیوں ہیں؟ ایک فیلڈ ایک ہی وقت میں کئی فیلڈز کی "تعریف" کر سکتا ہے، جیسا کہ EnvelopedData ڈھانچے میں ہوتا ہے۔ ڈیفائنڈ فیلڈز کی شناخت نام نہاد ڈی کوڈ پاتھ سے ہوتی ہے - یہ تمام ڈھانچے میں کسی بھی عنصر کی صحیح جگہ کی وضاحت کرتی ہے۔

آپ ہمیشہ نہیں چاہتے ہیں یا آپ کے پاس ہمیشہ یہ موقع نہیں ہے کہ آپ ان وضاحتوں کو خاکہ میں فوری طور پر شامل کریں۔ درخواست کے لیے مخصوص معاملات ہو سکتے ہیں جب OIDs اور ڈھانچے صرف فریق ثالث کے پروجیکٹ میں معلوم ہوں۔ PyDERASN ڈھانچے کو ضابطہ کشائی کے وقت ان وضاحتوں کو درست کرنے کی صلاحیت فراہم کرتا ہے:

ContentInfo().decode(data, ctx={"defines_by_path": ((
    (
        "content", DecodePathDefBy(id_signedData),
        "certificates", any, "certificate", "tbsCertificate",
        "extensions", any, "extnID",
    ),
    ((("extnValue",), {
        id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
        id_ce_basicConstraints: BasicConstraints(),
        [...]
        id_ru_subjectSignTool: SubjectSignTool(),
    }),),
),)})

یہاں ہم کہتے ہیں کہ تمام منسلک سرٹیفکیٹس کے لیے CMS SignedData میں، ان کے تمام ایکسٹینشنز (AuthorityKeyIdentifier، Basic Constraints، SubjectSignTool، وغیرہ) کو ڈی کوڈ کریں۔ ہم ڈی کوڈ پاتھ کے ذریعے اشارہ کرتے ہیں کہ کس عنصر کو ڈیفائنز کے ساتھ "متبادل" کرنے کی ضرورت ہے، گویا اسکیما میں اس کی وضاحت کی گئی ہے۔

آخر میں، PyDERASN میں چلانے کی صلاحیت ہے۔ کمانڈ لائن ASN.1 فائلوں کو ضابطہ کشائی کرنے کے لئے اور امیر ہے۔ خوبصورت پرنٹنگ. آپ ایک صوابدیدی ASN.1 کو ڈی کوڈ کر سکتے ہیں، یا آپ واضح طور پر بیان کردہ اسکیم کی وضاحت کر سکتے ہیں اور کچھ اس طرح دیکھ سکتے ہیں:

پائڈراسن: میں نے سلاٹ اور بلاب کے ساتھ ASN.1 لائبریری کیسے لکھی۔

ظاہر کردہ معلومات: آبجیکٹ آفسیٹ، ٹیگ کی لمبائی، لمبائی کی لمبائی، مواد کی لمبائی، EOC کی موجودگی (آکٹیٹس کے اختتام)، بی ای آر انکوڈنگ وصف، غیر معینہ لمبائی انکوڈنگ وصف، EXPLICIT ٹیگ کی لمبائی اور آفسیٹ (اگر کوئی ہے)، گھونسلے کی گہرائی ڈھانچے میں آبجیکٹ، IMPLICIT/EXPLICIT ٹیگ ویلیو، اسکیم کے مطابق آبجیکٹ کا نام، اس کی بنیاد ASN.1 قسم، SEQUENCE/SET OF کے اندر ترتیب نمبر، CHOICE قدر (اگر کوئی ہے)، انسانی پڑھنے کے قابل نام INTEGER/ENUMERATED/BIT STRING اسکیم کے مطابق، کسی بھی بنیادی قسم کی قیمت، اسکیم سے DEFAULT/OPTIONAL پرچم، اس بات کی علامت ہے کہ آبجیکٹ خود بخود ڈیفائنڈ BY کے طور پر ڈی کوڈ ہو گیا تھا اور جس OID کی وجہ سے ایسا ہوا، انسانی پڑھنے کے قابل OID۔

خوبصورت پرنٹنگ سسٹم کو خاص طور پر ڈیزائن کیا گیا ہے تاکہ یہ پی پی اشیاء کی ایک ترتیب تیار کرے جو الگ الگ ٹولز کا استعمال کرتے ہوئے تصور کیے جاتے ہیں۔ اسکرین شاٹ رینڈرر کو سادہ رنگین متن میں دکھاتا ہے۔ JSON/HTML فارمیٹ میں بھی پیش کنندہ موجود ہیں، تاکہ اسے ASN.1 براؤزر میں ہائی لائٹنگ کے ساتھ دیکھا جا سکے، جیسا کہ asn1js پروجیکٹ

دیگر لائبریریاں

یہ مقصد نہیں تھا، لیکن PyDERASN نمایاں طور پر نکلا۔ تیزی سے pyasn1 کے مقابلے میں۔ مثال کے طور پر، میگا بائٹ سائز کی CRL فائلوں کو ڈی کوڈ کرنے میں اتنا وقت لگ سکتا ہے کہ آپ کو انٹرمیڈیٹ ڈیٹا اسٹوریج فارمیٹس (تیز) کے بارے میں سوچنا پڑے گا اور ایپلیکیشن آرکیٹیکچر کو تبدیل کرنا پڑے گا۔ pyasn1 CRL کو ڈی کوڈ کرتا ہے۔ CACert.org میرے لیپ ٹاپ پر 20 منٹ سے زیادہ وقت لگتا ہے، جبکہ PyDERASN صرف 28 سیکنڈ لیتا ہے! ایک پروجیکٹ ہے۔ asn1crypto، جس کا مقصد کرپٹوگرافک ڈھانچے کے ساتھ تیزی سے کام کرنا ہے: یہ اسی CRL کو 29 سیکنڈ میں ڈی کوڈ کرتا ہے (مکمل طور پر، سستی سے نہیں)، لیکن Python3 (983 MiB بمقابلہ 498) کے تحت چلنے پر تقریباً دوگنا زیادہ RAM استعمال کرتا ہے، اور Python3.5 (2) کے تحت 1677 گنا میں بمقابلہ 488)، جبکہ pyasn1 4.3 گنا زیادہ استعمال کرتا ہے (2093 بمقابلہ 488)۔

ہم نے asn1crypto پر غور نہیں کیا، جس کا میں نے ذکر کیا، کیونکہ یہ منصوبہ ابھی ابتدائی دور میں تھا اور ہم نے اس کے بارے میں نہیں سنا تھا۔ اب ہم اس کی سمت بھی نہیں دیکھیں گے، کیونکہ میں نے فوراً دریافت کیا کہ وہی جنرلائزڈ ٹائم کوئی من مانی شکل نہیں لیتا، اور سیریلائزیشن کے دوران یہ خاموشی سے ایک سیکنڈ کا ایک حصہ ہٹا دیتا ہے۔ یہ X.509 سرٹیفکیٹس کے ساتھ کام کرنے کے لیے قابل قبول ہے، لیکن عام طور پر یہ کام نہیں کرے گا۔

اس وقت، PyDERASN سب سے سخت مفت Python/Go DER ڈیکوڈر ہے جس کے بارے میں میں جانتا ہوں۔ میرے پیارے گو کی انکوڈنگ/asn1 لائبریری میں سخت چیک نہیں آبجیکٹ شناخت کنندہ اور UTCTtime/Generalized Time سٹرنگز۔ بعض اوقات سختی راستے میں آ سکتی ہے (بنیادی طور پر پرانی ایپلی کیشنز کے ساتھ پسماندہ مطابقت کی وجہ سے جسے کوئی بھی ٹھیک نہیں کرے گا)، لہذا PyDERASN گزر سکتا ہے۔ مختلف ترتیبات کمزور چیک.

پروجیکٹ کوڈ ہر ممکن حد تک آسان ہونے کی کوشش کرتا ہے۔ پوری لائبریری ایک فائل ہے۔ کوڈ کو غیر ضروری کارکردگی کی اصلاح اور DRY کوڈ کے بغیر سمجھنے کی آسانی پر زور دیتے ہوئے لکھا گیا ہے۔ یہ، جیسا کہ میں پہلے ہی کہہ چکا ہوں، UTCTime/GeneralizedTime سٹرنگز کے ساتھ ساتھ REAL, RELATIVE OID, EXTERNAL, INSTANCE OF, EmbedDed PDV, CHARACTER STRING ڈیٹا کی قسموں کی مکمل BER ڈی کوڈنگ کی حمایت نہیں کرتا ہے۔ دیگر تمام معاملات میں، میں ذاتی طور پر ازگر میں دوسری لائبریریوں کو استعمال کرنے کا نقطہ نظر نہیں آتا۔

میرے تمام منصوبوں کی طرح، جیسے پیگوسٹ, GoGOST, این این سی پی, GoVPN، PyDERASN مکمل طور پر ہے۔ مفت سافٹ ویئر، شرائط کے تحت تقسیم کیا گیا۔ LGPLv3+، اور مفت ڈاؤن لوڈ کے لیے دستیاب ہے۔ استعمال کی مثالیں ہیں۔ یہاں اور PyGOST ٹیسٹ.

سرگئی ماتویف, سائپرپنک، رکن ایس پی او فاؤنڈیشن, Python/Go ڈویلپر، چیف ماہر FSUE "STC "اٹلس".

ماخذ: www.habr.com

نیا تبصرہ شامل کریں