
اليوم ، أصبح استخدام الشهادات الرقمية X509 v.3 شائعًا. يستخدمهم المزيد والمزيد من الأشخاص للوصول إلى موقع ويب خدمة الدولة ، دائرة الضرائب الفيدرالية ، المزايدة الإلكترونية ، إلخ. والمزيد والمزيد من الناس يريدون أن يعرفوا ما هو موجود في هذه الشهادة التي تسمى "الصدر". وإذا كانت الشهادة تماثلية لجواز السفر ، فكيف يمكن قراءتها / عرضها. نعم ، في أنظمة التشغيل هناك العديد من الأدوات المساعدة للعرض. لكنهم سوف يقدمون القليل للمواطن العادي. خذ على سبيل المثال ، الأداة المساعدة gcr-viewer ، والتي ، في الواقع ، هي الأداة القياسية للعرض في أنظمة Linux ، وبالتالي في
أنظمة التشغيل المحلية :

المشاهد القياسية
الأداة جيدة الصنع ومريحة. بشكل عام ، يُقصد به أن يكون أداة مساعدة عامة لعرض الملفات التي تحتوي على بيانات بتنسيقات تشفير مختلفة (شهادات ، طلبات ، توقيعات إلكترونية / PKCS # 7 ، حاويات محمية PKCS # 12 ، إلخ). ولكن ، لسوء الحظ ، تم تصميمه للتشفير الغربي ولا يأخذ في الاعتبار المساعدات التي يتم إدخالها في بلدك. وإذا نظرت إلى لقطة الشاشة ، فعندما يتم عرض المعلومات حول صاحب الشهادة ، تظهر أحرف غير مفهومة. على اليسار هي oid s ، وعلى اليمين في النموذج السادس عشر ، الهيكل asn1 بقيمه. في هذه الحالة ، هذه هي OGRN (1.2.643.100.1) و SNILS (1.2.643.100.3) و TIN (1.2.643.3.131.1.1). وهذه هي الطريقة التي يجب على المواطن العادي التأكد من أن هذه هي بياناته. لا تعتقد أن هذا موجود فقط على نظام Linux ، بل هو ميزة شائعة لأي عارض شهادات. وإذا نظرت إلى أبعد من ذلك ، يصبح كل شيء غير مفهوم:

تظهر بعض الملحقات والمعرفات والقيم. في هذه الحالة ، يخفي oid om 1.2.643.100.111 اسم شهادة حماية معلومات التشفير ، والتي استخدمها المستخدم لإنشاء زوج المفاتيح ، والمفتاح الخاص الذي استخدم منه لتوقيع طلب الشهادة ، والمفتاح العام الذي توجد منه الشهادة:

وهنا ، يفهم القليل من قبل صاحب الشهادة. إنه لا يفهم حتى الخوارزمية المستخدمة لإنشاء المفتاح ، إما GOST R 34.10-2001 ، أو GOST R 34.10-2012 وبأي طول مفتاح.
يمكنك الاستمرار في إعطاء أمثلة. على سبيل المثال ، إذا كانت صلاحية الشهادة واضحة ، فأين المفتاح؟
هناك سؤالان آخران يرغب أصحاب الشهادات في الحصول على إجابة لهما: أين يمكنني الحصول على سلسلة شهادات الجذر (أو حتى الحصول على أفضل منها فقط) وسؤال مماثل في قائمة الشهادات الملغاة.
وأخيرًا ، أرغب في الحصول على أداة مساعدة عالمية تأخذ في الاعتبار ميزات PKI / PKI الروسية ، والتي تعد بالفعل منصة مشتركة وتعمل على
أنظمة تشغيل محلية وغير
محلية . ما لتطوير؟ بالطبع في لغة البرمجة النصية ، إذا كان ذلك فقط بسبب طبيعتها عبر منصة.
ثم تذكرت أن لغة النص البرمجي الجميلة Tcl (لغة أوامر الأداة) قد احتفلت مؤخرًا بمرور
30 عامًا على تأسيسها . إنه لمن دواعي سروري أن البرنامج على ذلك. يحتوي على عدد كبير من الملحقات (الحزمة) التي تسمح بكل شيء تقريبًا. لذلك ، للعمل مع ASN- الهياكل هناك حزمة asn. علاوة على ذلك ، للعمل مع الشهادات (نحن مهتمون بتوزيعها في هذه الحالة) هناك حزمة pki. ولتطوير واجهة رسومية ، هناك حزمة Tk.
يمكن قول نفس الشيء عن بيتون مع تكينتر ، وعن بيرل وعن روبي. يمكن للجميع اختيار وفقا لذوقهم. نتوقف عند حفنة من Tcl / Tk.
سنستعير تصميم الرسوم للأداة من الأداة المساعدة gcr-viewer. وشرط واحد آخر.
نظرًا لأن لدى Habr إصدارًا
باللغة الإنجليزية ، فقد أردت الأداة أن يكون لها واجهات مختلفة (الروسية / الإنجليزية). ولكن هذا ليس السبب الرئيسي. والأهم من ذلك ، أن المزيد والمزيد من مواطني العالم الغربي أصبحوا مواطنين في الاتحاد الروسي ، على سبيل المثال ، الممثل العالمي الشهير ديبارديو. قد يعترضون: إنه فرنسي. لكنني أيضًا مترجم عسكري من الفرنسية:

لذلك من السهل إضافة واجهة فرنسية. لكنني أعتقد أن Depardieu لا يوجد لديه مشاكل مع اللغة الإنجليزية. من ناحية أخرى ، فإن بلدنا متعدد الجنسيات وسيكون من الرائع أن يكون لدى البرنامج المحلي ونظام التشغيل المحلي عدة واجهات وطنية على الأقل.
مع التقدم قليلاً ، هذا ما جاء منه:

نحن ندعو مترجم
لذلك ، لنبدأ بـ "المترجم". في لقطة الشاشة ، يختبئ تحت العلم الوطني. الشرط الرئيسي للمترجم هو تزامن الترجمة ، أي القدرة على التحول إلى لغة أخرى في أي وقت. يتم تنفيذ وظائف المترجم في Tcl / Tk بواسطة حزمة msgcat:
package require msgcat
لتعيين اللغة الحالية ، استخدم الأمر التالي:
msgcat::mclocale ru
يتم تخزين مفردات "المترجم" في ملف ru.msg على النحو التالي:
# msgcat::mcset # mcset namespace import -force msgcat::mcset # mcset ru "Language" "" …
ما يلي هو نص الاختبار
النصي مع المترجم: #!/usr/bin/wish -f # msgcat package require msgcat # ru msgcat::mclocale ru # ::msgcat::mc # mc namespace import msgcat::mc # [msgcat::mclocale].msg. # . msgcat::mcload [file join [file dirname [info script]]] # image create photo rf_32x21_f -file rf_32x21.png image create photo gb_32x21_f -file gb_32x21.png #, label .lab -text "[mc Language]: " -relief flat -bd 0 –bg snow -anchor sw -width 10 button .but_lang -image rf_32x21_f -command ::changelang -relief flat -bd 0 pack .lab -side left -pady {2 0} pack .but_lang -side left # proc ::changelang {} { # # if {[msgcat::mclocale] == "ru"} { msgcat::mclocale en .but_lang configure -image gb_32x21_f } else { msgcat::mclocale ru .but_lang configure -image rf_32x21_f } # .lab configure -text "[mc Language]: " }
في هذا البرنامج النصي ، يعمل الإجراء :: changelang كمترجم ، والذي يتم استدعاؤه عند الضغط على زر .but_lang مع العلم.
إذا قمت بتشغيل هذا البرنامج النصي ، فسترى بوضوح كيف يعمل المترجم:

الحصول على المفتاح العمومي
الآن وبعد أن قررنا وجود مترجم ، دعنا نواصل تحليل الشهادة. للقيام بذلك ، نحتاج إلى حزمة pki:
package require pki).
تم تصميم حزمة pki للعمل مع مفاتيح وشهادات خوارزمية RSA. إذا تم إنشاء الشهادة (proc :: pki :: x509 :: parse_cert) بنوع مختلف من المفتاح ، فلن نتلقى معلومات حول هذا المفتاح:
# Handle RSA public keys by extracting N and E switch -- $ret(pubkey_algo) { "rsaEncryption" { set pubkey [binary format B* $pubkey] binary scan $pubkey H* ret(pubkey) ::asn::asnGetSequence pubkey pubkey_parts ::asn::asnGetBigInteger pubkey_parts ret(n) ::asn::asnGetBigInteger pubkey_parts ret(e) set ret(n) [::math::bignum::tostr $ret(n)] set ret(e) [::math::bignum::tostr $ret(e)] set ret(l) [expr {int([::pki::_bits $ret(n)] / 8.0000 + 0.5) * 8}] set ret(type) rsa } }
والمثير للدهشة أن خوارزمية المفتاح العام ما زالت تُرجع (ret (pubkey_algo))
الموقف هو نفسه عند تحليل طلب الشهادة (proc :: pki :: pkcs :: parse_csr):
# Parse public key, based on type switch -- $pubkey_type { "rsaEncryption" { set pubkey [binary format B* $pubkey] ::asn::asnGetSequence pubkey pubkey_parts ::asn::asnGetBigInteger pubkey_parts key(n) ::asn::asnGetBigInteger pubkey_parts key(e) set key(n) [::math::bignum::tostr $key(n)] set key(e) [::math::bignum::tostr $key(e)] set key(l) [expr {2**int(ceil(log([::pki::_bits $key(n)])/log(2)))}] set key(type) rsa } default { return -code error "Unsupported key type: $pubkey_type" } }
لكنه هنا يعود حتى معلومات عن الخطأ. ولكن اليوم ، بالإضافة إلى RSA ، على سبيل المثال ، يتم استخدام مفاتيح المنحنيات الإهليلجية للاتحاد الأوروبي ، بما في ذلك GOST R 34.10-2012 (GOST R 34.10-2001 أيضًا في الوقت الحالي) ،.
ولكن يكفي بشكل افتراضي إرجاع بنية ASN للمفتاح العمومي الموجودة في الشهادة أو الطلب ، وسيعمل المستخدم نفسه على تحليل المفتاح العمومي وفقًا لنوع المفتاح. للقيام بذلك ، ما عليك سوى إضافة بنية ASN للمفتاح العام في القيم السداسية عشرية إلى القيم التي يتم إرجاعها:
proc ::pki::x509::parse_cert {cert} { . . . ::asn::asnGetSequence cert subject ::asn::asnGetSequence cert pubkeyinfo # ASN- . binary scan $pubkeyinfo H* ret(pubkey_pubkeyinfo) . . . }
كل شيء ، لا شيء آخر للقيام به. وبهذه الطريقة ، يقوم الإجراء :: pki :: x509 :: parse_cert بإرجاع معظم ملحقات الشهادة لسبب بسيط هو أنه لا يعرف كيفية تحليلها (على سبيل المثال ، topicSignTool بشهاداتنا المؤهلة) ، أي يعطي حسب تقدير المستخدم.
من ناحية أخرى ، يُرجع الإجراء :: pki :: x509 :: parse_cert إحدى نتائج
شهادة tbs التي تحتوي على كافة المعلومات من الشهادة ، باستثناء توقيعها (توقيع) ونوع التوقيع (signature_algo):
# set fd [open «cert.pem» r] chan configure –translation binary set datacert [read $fd] close $fd # array set cert_parse [::pki::x509::parse_cert $datacert] # tbs- set cert_tbs_hex $cert_parse(cert)
نكتب الإجراء الخاص باستخراج معلومات المفتاح العام من شهادة tbs:
proc ::pki::x509::parse_cert_pubkeyinfo {cert_tbs_hex} { array set ret [list] set wholething [binary format H* $cert_tbs_hex] ::asn::asnGetSequence wholething cert ::asn::asnPeekByte cert peek_tag if {$peek_tag != 0x02} { # Version number is optional, if missing assumed to be value of 0 ::asn::asnGetContext cert - asn_version ::asn::asnGetInteger asn_version ret(version) } ::asn::asnGetBigInteger cert ret(serial_number) ::asn::asnGetSequence cert data_signature_algo_seq ::asn::asnGetObjectIdentifier data_signature_algo_seq ret(data_signature_algo) ::asn::asnGetSequence cert issuer ::asn::asnGetSequence cert validity ::asn::asnGetUTCTime validity ret(notBefore) ::asn::asnGetUTCTime validity ret(notAfter) ::asn::asnGetSequence cert subject ::asn::asnGetSequence cert pubkeyinfo # hex asn- binary scan $pubkeyinfo H* ret(pubkeyinfo) return $ret(pubkeyinfo) }
ولأننا مهتمون بالتشفير الروسي ، فسنكتب على الفور إجراء تحليل المفتاح العمومي GOST:
proc parse_key_gost {pubkeyinfo_hex} { array set ret [list] set pubkeyinfo [binary format H* $pubkeyinfo_hex] ::asn::asnGetSequence pubkeyinfo pubkey_algoid ::asn::asnGetObjectIdentifier pubkey_algoid ret(pubkey_algo) #, - if {[string first "1 2 643 " $ret(pubkey_algo)] == -1} { return [array get ret] } ::asn::asnGetBitString pubkeyinfo pubkey set pubkey [binary format B* $pubkey] # binary scan $pubkey H* ret(pubkey) ::asn::asnGetSequence pubkey_algoid pubalgost #OID - ::asn::asnGetObjectIdentifier pubalgost ret(paramkey) #OID - ::asn::asnGetObjectIdentifier pubalgost ret(hashkey) #puts "ret(paramkey)=$ret(paramkey)\n" #puts "ret(hashkey)=$ret(hashkey)\n" #parray ret # : , return [array get ret] }
نعم ، فاتني ذلك تقريبًا: بعد تحميل حزمة pki ، تحتاج إلى إضافة إلى صفيف :: pki :: oids oids التي تميز GOST وشهادة مؤهلة أو ببساطة غائبة في هذا الصفيف:
package require pki # oid- set ::pki::oids(1.2.643.100.1) "OGRN" set ::pki::oids(1.2.643.100.5) "OGRNIP" set ::pki::oids(1.2.643.3.131.1.1) "INN" set ::pki::oids(1.2.643.100.3) "SNILS" set ::pki::oids(1.2.643.2.2.19) "GOST R 34.10-2001" set ::pki::oids(1.2.643.7.1.1.1.1) "GOST R 34.10-2012-256" set ::pki::oids(1.2.643.7.1.1.1.2) "GOST R 34.10-2012-512" set ::pki::oids(1.2.643.2.2.3) "GOST R 34.10-2001 with GOST R 34.11-94" set ::pki::oids(1.2.643.7.1.1.3.2) "GOST R 34.10-2012-256 with GOSTR 34.11-2012-256" set ::pki::oids(1.2.643.7.1.1.3.3) "GOST R 34.10-2012-512 with GOSTR 34.11-2012-512" set ::pki::oids(1.2.643.100.113.1) "KC1 Class Sign Tool" set ::pki::oids(1.2.643.100.113.2) "KC2 Class Sign Tool" . . .
يمكنك أيضًا تجديد مفردات المترجم عن طريق الإضافة إلى ملف ru.msg:
mcset ru "GOST R 34.10-2001" " 34.10-2001" mcset ru "GOST R 34.10-2012-256" " 34.10-2012-256" mcset ru "GOST R 34.10-2012-512" " 34.10-2012-512" mcset ru "GOST R 34.10-2001 with GOST R 34.11-94" " 34.10-2001 34.11-94" mcset ru "GOST R 34.10-2012-256 with GOSTR 34.11-2012-256" " 34.10-2012-256 34.11-2012-256" mcset ru "GOST R 34.10-2012-512 with GOSTR 34.11-2012-512" " 34.10-2012-512 34.11-2012-512" . . .
:

سلسلة شهادة الجذر وقائمة إبطال الشهادات
لقد تمت مناقشة كيفية الحصول على سلسلة من شهادات الجذر مسبقًا. عن طريق القياس ، يتم كتابة الإجراء للحصول على قائمة شهادات COS / CRL الملغاة. يمكن العثور على الكود المصدري للأداة المساعدة وتوزيعاتها لنظامي التشغيل Linux و OS X (macOS) و MS Windows
في التعليمات البرمجية المصدر ، يمكنك العثور على جميع الإجراءات الخاصة بتحليل ملحقات الشهادة.
لمعارضي Tk (Tcl / Tk ، Python / Tkinter ، وما إلى ذلك) ، أقترح إيجاد ، كما يقولون ، 10 (عشرة) اختلافات بين الأداة المساعدة اثنين: الأداة المساعدة gcr-viewer المكتوبة بـ gtk والأداة المساعدة certViewer المطورة في Tk:

PKCS # 11 الرموز / البطاقة الذكية الشهادات
تحدثنا أعلاه عن العمل مع الشهادات (التصفح ، الحصول على سلسلة شهادات الجذر ، قوائم الشهادات الملغاة ، بصمات الأصابع بواسطة sha1 و sha256 ، إلخ) المخزنة في الملفات. ولكن لا تزال هناك شهادات مخزنة على الرموز PKCS # 11 / البطاقات الذكية. والرغبة الطبيعية ليست فقط لرؤيتهم ، ثم التصدير إلى ملف. كيفية القيام بذلك ، سوف نوضح في المقالة التالية:
