
في وقت واحد ، ألهمني تطبيق خوارزميات التشفير المحلية في مكتبة libgcrypt كثيرًا. أصبح من الممكن استخدام
هذه الخوارزميات في كليوباترا وفي Kmail و GnuPg بشكل عام ، للنظر في مكتبة libgcrypt
كبديل عن openssl مع محرك GOST. وكان كل شيء رائعا حتى يوم الجمعة الماضي.
تمت مطالبتي بالتحقق من التوقيع الإلكتروني لـ GOST R 34.10-2012-256 لوثيقة تم إنشاؤها في Microsoft Office على MS Windows. وقررت التحقق من ذلك في كليوباترا (لدي لينكس). وماذا برأيك ، ظهر أن التوقيع خطأ. الشكوك تسللت. قررت التحقق من
openssl مع محرك
GOST . تم التحقق من التوقيع بنجاح. أعيد توقيع الملف بشكل عاجل في كليوباترا ولم ينجح في التحقق من MS Windows. حاولنا التوقيع والتحقق من الملفات الأخرى ، كل شيء على ما يرام. كان السؤال ما هي المشكلة؟ نظرًا لأن تجزئة المستند متورطة في التوقيع ، فقد تقرر التحقق من حساب التجزئة من خلال برامج مختلفة. بادئ
ذي بدء ، تم تضمين تطبيقات مفتوحة المصدر لـ stribog :
ثم حدثت صدمة! تزامن التجزئة المحسوب بواسطة "تطبيق Degtyarev الشهير" مع التجزئة المحسوب في openssl مع GOST للنهاية ، لكنه لم يتطابق مع قيمة التجزئة المحسوبة باستخدام libgcrypt و libressl.
كيف كان
ru_crypt على حق عندما كتب في بداية
مقالته :
أحذرك فورًا من أنني لم أتحقق من صحة التطبيقات.
بالمناسبة ، يقول المعيار في GOST R 34.10-2012 أيضًا أن أمثلة التحكم هي للإشارة فقط. يجب أن يكون مفهوما بوضوح أن حالات الاختبار لا تضمن أن التطبيقات المختلفة تعطي نفس النتيجة لجميع المناسبات.
لحساب قيم التجزئة ، تم استخدام الأدوات المساعدة التالية:
1) openssl
$ openssl dgst [–md_gost12_256|-md_gost12_512] <file>
2) libressl
$libressl dgst [–streebog256|streebog512] <file>
3) libgcrypt
$gchash [stribog256|stribog512] <file>
4) التنفيذ الشهير لـ Degtyarev
$gost3411-2012 [-2|-5] <file>
هنا شيء مثير للاهتمام أيضًا: في النسخ اللاتيني ، يكتب stribogs إما stribog أو streebog. سيكون من الجميل أن يأتي إلى التوحيد. وهكذا يبدو أن هذه وظائف مختلفة. شخصيا ، أنا أفضل الخيار الأول - stribog.
كنت بحاجة إلى محكم.
كمحكّم ، تقرر استخدام الرمز المميز PKCS # 11 RUTOKEN EDS-2.0 ، والذي يدعم معايير التشفير الروسية GOST R 34.10-2012 و GOST R 34.11-2012 و VKO GOST R 34.10-2012 (RFC 7836) بطول مفتاح يبلغ 256 و 512 بت ، ومصدقة من قبل جهاز الأمن الفيدرالي الروسي كوسيلة لحماية معلومات التشفير (CPSI) والتوقيع الإلكتروني.
بالإضافة إلى ذلك ، يتم توزيع الرمز المميز RUTOKEN EDS-2.0 على نطاق واسع والعديد من
شهادات المتجر عليه للوصول إلى خدمات
الدولة والبوابات الأخرى.
لحساب قيمة التجزئة على الرمز المميز ، سنستخدم البرنامج النصي test_digest.tcl في
Tcl :
test_digest.tcl #! /usr/bin/env tclsh package require pki lappend auto_path . package require pki::pkcs11 # PKCS#11 set pkcs11_module "/usr/local/lib64/librtpkcs11ecp_2.0.so" #set pkcs11_module "/usr/local/lib64/libls11sw2016.so" puts "Connect the Token and press Enter" gets stdin yes set handle [pki::pkcs11::loadmodule $pkcs11_module] set slots [pki::pkcs11::listslots $handle] foreach slotinfo $slots { set slotid [lindex $slotinfo 0] set slotlabel [lindex $slotinfo 1] set slotflags [lindex $slotinfo 2] if {[lsearch -exact $slotflags TOKEN_PRESENT] != -1} { set token_slotlabel $slotlabel set token_slotid $slotid # break } } proc usage {use error} { puts "Copyright(C) Orlov Vladimir (http://soft.lissi.ru) 2019" if {$use == 1} { puts $error puts "Usage:\ndigest <stribog256|stribog512> <file for digest>\n" } } set countcert [llength $argv] if { $countcert != 2 } { usage 1 "Bad usage!" exit } set digest_algo [lindex $argv 0] if {$digest_algo != "stribog256" && $digest_algo != "stribog512"} { usage 1 "Bad usage!" exit } set file [lindex $argv 1] if {![file exists $file]} { usage 1 "File $file not exist" exit } puts "Loading file for digest: $file" set fd [open $file] chan configure $fd -translation binary set cert_user [read $fd] close $fd if {$cert_user == "" } { usage 1 "Bad file: $file" exit } set aa [dict create pkcs11_handle $handle pkcs11_slotid $token_slotid] set digest_hex [pki::pkcs11::digest $digest_algo $cert_user $aa] puts "digest_hex=\n$digest_hex" exit
متى يظهر هذا التناقض في التنفيذ؟ حتى الآن ، كان من الممكن تحديد أن هذا التناقض يحدث عند حساب تجزئة ملفات المستندات التي تم إنشاؤها في MS Office. علاوة على ذلك ، تعتبر التجزئة من 143 بايت الأولى هي نفسها ، وعند حساب التجزئة من 144 بايت ، تختلف القيم.
أول 143 بايت في الست عشري تبدو مثل هذا:
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000002400000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
احفظها في الملف Doc1_143_hex.txt.
أول 144 بايت في الست عشري تبدو مثل هذا:
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000002400000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
احفظها في الملف Doc1_144_hex.txt.
من المريح استخدام البرنامج النصي hex2bin.tcl للترجمة من الست عشري إلى النموذج الثنائي:
#!/usr/bin/tclsh proc usage {use error} { if {$use == 1} { puts $error puts "Usage:\nhex2bin <file with hex> <file for bin>\n" } } set countcert [llength $argv] if { $countcert != 2 } { usage 1 "Bad usage!" exit } set file [lindex $argv 0] if {![file exists $file]} { usage 1 "File $file not exist" exit } set fd [open $file] chan configure $fd -translation binary set cert_user [read $fd] close $fd if {$cert_user == "" } { usage 1 "Bad file with hex: $file" exit } set cert_user [binary format H* $cert_user] set fd [open [lindex $argv 1] w] chan configure $fd -translation binary puts -nonewline $fd $cert_user close $fd
تحويل الشفرة السداسية عشرية إلى ثنائي:
$./hex2bin Doc1_143_hex.txt Doc1_143.bin $./hex2bin Doc1_144_hex.txt Doc1_144.bin $
يمكنك الآن التحقق من كيفية حساب التجزئة من خلال تطبيقات مختلفة:
أولاً ، خذ بعين الاعتبار تجزئة الملف Doc1_143 ، bin:
$ ./openssl dgst -md_gost12_256 Doc1_143.bin md_gost12_256(Doc1_143.bin)= e63bd3edc44f9a03fece4198b690a8ae291b973ae61b2a0f512a9a7479431a63 $ ./libressl dgst -streebog256 Doc1_143.bin streebog256(Doc1_143.bin)= e63bd3edc44f9a03fece4198b690a8ae291b973ae61b2a0f512a9a7479431a63 $ ./gchash stribog256 Doc1_143.bin e63bd3edc44f9a03fece4198b690a8ae291b973ae61b2a0f512a9a7479431a63 Doc1_143.bin $ ./gost3411-2012 -2 Doc1_143.bin GOST R 34.11-2012 (Doc1_143.bin) = e63bd3edc44f9a03fece4198b690a8ae291b973ae61b2a0f512a9a7479431a63 $
لقد حان الوقت الأكثر أهمية ، لحظة التحقق على نظام معتمد لحماية معلومات التشفير:
$ ./test_digest.tcl stribog256 Doc1_143.bin Connect the Token and press Enter Loading file for digest: Doc1_143.bin digest_hex= e63bd3edc44f9a03fece4198b690a8ae291b973ae61b2a0f512a9a7479431a63 $
كما ترون ، انتهى كل شيء إلى الأبد.
دعونا نرى ما يحدث لملف Doc1_144.bin:
$ ./openssl dgst -md_gost12_256 Doc1_144.bin md_gost12_256(Doc1_144.bin)= c766085540caaa8953bfcf7a1ba220619cee50d65dc242f82f23ba4b180b18e0 $ ./libressl dgst -streebog256 Doc1_144.bin streebog256(Doc1_144.bin)= 3965c99777eb1b64c783496fe950aa6540bc7baa399a3889995145afbdd76250 $
هذا كل شيء ، وقيم التجزئة لا تتطابق. من أجل نقاء التجربة ، نتحقق من التطبيقات المتبقية:
$ ./gchash_1.7.10 stribog256 Doc1_144.bin 3965c99777eb1b64c783496fe950aa6540bc7baa399a3889995145afbdd76250 Doc1_144.bin $ ./gost3411-2012 -2 Doc1_144.bin GOST R 34.11-2012 (Doc1_144.bin) = c766085540caaa8953bfcf7a1ba220619cee50d65dc242f82f23ba4b180b18e0 $ ./test_digest.tcl stribog256 Doc1_144.bin Connect the Token and press Enter Loading file for digest: Doc1_144.bin digest_hex= c766085540caaa8953bfcf7a1ba220619cee50d65dc242f82f23ba4b180b18e0 $
تتطابق التجزئة المحسوبة بواسطة "تطبيق Degtyarev الشهير" مع التجزئة المحسوب في openssl مع محرك GOST ، لكنه لا يتطابق مع قيمة التجزئة المحسوبة باستخدام libgcrypt و libressl.
نحصل على نتيجة مماثلة إذا نظرنا في التجزئة stribog512.
هناك استنتاج واحد. إذا كنت ترغب في أن يكون التوقيع الإلكتروني GOST R 34.10-2012 الذي تم إنشاؤه بواسطة libressl و libgcrypt (أو ربما آخرين) متوافقًا مع opensl ، والأهم من ذلك ، مع حماية معلومات التشفير المعتمدة في نظام شهادات FSB في روسيا ، استخدم التحقق تطبيقات لحساب التجزئة. آمل أن يتجنب هذا المنشور العديد من سوء الفهم ، وسيساعد مؤلفو تطبيق stribog في libressl و libgrypt وربما آخرين في القضاء على هذه الاختلافات. اليوم ، يجب أن أعترف ، في المنتجات المذكورة أعلاه ، أنها في الواقع ليست GOST R 34.10-2012 التي يتم تنفيذها ، ولكن شيء آخر. هذه خوارزمية مختلفة. من المحتمل أن يكون مثال الاختبار المحدد مدرجًا كمثال اختبار لـ GOST R 34.10-2012. وانا ذاهب لتحرير libgcrypt لكليوباترا و KMail. أسطورة كليوبارت والتشفير الروسي لم تنته بعد.
ملحوظة: كانت المقالة جاهزة بالفعل عندما قال زميلي أن التناقض بين التطبيقات يظهر عند مواجهة سلسلة طويلة بما فيه الكفاية من 0xFF. هي ، هذا التسلسل ، بالمناسبة ، موجود في بداية ملفات doc من MS Office. راجعت ، على ما هو عليه. احتوى الملف على 189 بايت.