PyDERASN: كما أضفت دعم البيانات الضخمة

أكمل المقال الأخير حول PyDERASN - برنامج الترميز المجاني ASN.1 DER / CER / BER في Python. على مدار العام الماضي ، منذ كتابته ، بالإضافة إلى جميع الأشياء الصغيرة ، والتصحيحات الطفيفة ، وحتى التحقق من البيانات الأكثر صرامة (على الرغم من أنه قبل أن يكون أصعب برامج الترميز المجانية المعروفة لي) ، ظهرت وظائف في هذه المكتبة للعمل مع كميات كبيرة من البيانات - لا الزحف إلى ذاكرة الوصول العشوائي. أريد أن أتحدث عن هذا في هذه المقالة.

متصفح ASN.1

المشاكل / المهام


  • CRL:
    , (CA) X.509 . , CRL (certificate revocation list). CRL CACert.org, 8.72 MiB, PyDERASN- Python 3.6 ( asn1crypto pyasn1 ). 416 . . , . .
  • CMS:
    CMS (Cryptographic Message Syntax)
    // . ,
    SignedData , ,
    , - EnvelopedData
    .

    CMS. , CMS detached data, - , . 10 GiB 20 GiB : 10 GiB . .


ما هي كائنات ASN.1 التي يمكن أن تكون كثيفة الاستخدام للموارد ، وتستهلك مساحة كبيرة من الذاكرة؟ الوحيد تسلسل / SET OF التي تحتوي على العديد من الكائنات (مئات الآلاف في حالة CACert.org)، وجميع أنواع السلاسل * (كما في حالة إشكالية الثانية). نظرًا لأن إحدى مزايا المبرمج هي الكسل (وفقًا لـ Larry Wall) ، فسوف نحاول التغلب على مشكلات استهلاك الموارد بأقل تغيير في رمز المكتبة.

* كائنات STRING ، من وجهة نظر برنامج الترميز ، لا تختلف تقريبًا عن بعضها البعض ويتم تنفيذها في المكتبة بواسطة فئة مشتركة واحدة. ما هو الترميز في OCTET STRING في DER؟

return tag + len_encode(len(value)) + value

من الواضح أن القيمة لا يجب أن تكون في ذاكرة الوصول العشوائي طوال هذا الوقت. يجب أن يكون كائنًا شبيهًا بالبايت يمكنك من خلاله معرفة الطول.

عرض الذاكرة يفي بهذه الشروط. ومع ذلك ، يمكن إجراء عرض الذاكرة عن طريق mmap على أي ملف مؤقت تم تقليله بالفعل في الذاكرة 20 GiB 10 GiB لنسخ قاعدة بيانات CMS إلى النصف: يكفي تحديد قيمة OCTET STRING s (أو أي * STRING s أخرى) على غرار عرض الذاكرة . لإنشائه ، لدى PyDERASN وظيفة مساعدة:

from pyderasn import file_mmaped
with open("dump.sql.zst", "rb") as fd:
    ... = OctetString(file_mmaped(fd))

إذا أردنا فك شفرة كمية كبيرة من البيانات ، فيمكن أيضًا استخدام عرض الذاكرة لفك الشفرة:

from pyderasn import file_mmaped
with open("dump.sql.zst", "rb") as fd:
    obj = Schema.decode(file_mmaped(fd))

نعتبر المشكلة مع * STRING يتم حلها جزئيًا. العودة إلى إنشاء قائمة إبطال الشهادات (CRL) ضخمة. ما هو شكلها؟

CertificateList SEQUENCE
. tbsCertList: TBSCertList SEQUENCE
. . version: Version INTEGER v2 (01) OPTIONAL
. . signature: AlgorithmIdentifier SEQUENCE
. . issuer: Name CHOICE rdnSequence
. . thisUpdate: Time CHOICE utcTime
. . nextUpdate: Time CHOICE utcTime OPTIONAL
. . revokedCertificates: RevokedCertificates SEQUENCE OF OPTIONAL
. . . 0: RevokedCertificate SEQUENCE
. . . . userCertificate: CertificateSerialNumber INTEGER 17 (11)
. . . . revocationDate: Time CHOICE utcTime UTCTime 2003-04-01T14:25:08
. . . 1: RevokedCertificate SEQUENCE
. . . . userCertificate: CertificateSerialNumber INTEGER 20 (14)
. . . . revocationDate: Time CHOICE utcTime UTCTime 2002-10-01T02:18:01

                                 [...]

. . . 415753: RevokedCertificate SEQUENCE
. . . . userCertificate: CertificateSerialNumber INTEGER 1341859 (14:79:A3)
. . . . revocationDate: Time CHOICE utcTime UTCTime 2020-02-08T06:51:56
. . . 415754: RevokedCertificate SEQUENCE
. . . . userCertificate: CertificateSerialNumber INTEGER 1341860 (14:79:A4)
. . . . revocationDate: Time CHOICE utcTime UTCTime 2020-02-08T06:53:01
. . . 415755: RevokedCertificate SEQUENCE
. . . . userCertificate: CertificateSerialNumber INTEGER 1341861 (14:79:A5)
. . . . revocationDate: Time CHOICE utcTime UTCTime 2020-02-08T07:25:06
. signatureAlgorithm: AlgorithmIdentifier SEQUENCE
. signatureValue: BIT STRING 4096 bits

قائمة طويلة من هياكل الشهادات المبطلة الصغيرة . في هذه الحالة ، يحتوي فقط على الرقم التسلسلي للشهادة ووقت إبطالها. ما هو ترميز DER الخاص به؟

value = b"".join(revCert.encode() for revCert in revCerts)
return tag + len_encode(len(value)) + value

مجرد سلسلة من تمثيلات DER لكل عنصر فردي في هذه القائمة. هل نحن بحاجة إلى أن يكون مقدما كل هذه مئات الآلاف من الكائنات في سياق تسلسلها إلى 15 بايت من تمثيل DER؟ من الواضح أنه لا. لذلك ، نستبدل قائمة الكائنات بمكرر / مولد. على الأرجح ، سيعتمد إنشاء قائمة إبطال الشهادات (CRL) على البيانات من نظام إدارة قواعد البيانات (DBMS):

def revCertsGenerator(...):
    for row in db.cursor:
        yield RevokedCertificate((
            ("userCertificate", CertificateSerialNumber(row.serial)),
            ("revocationDate", Time(("utcTime", UTCTime(row.revdate)))),
        ))

crl["tbsCertList"]["revokedCertificates"] = revCertsGenerator()

الآن نحن لا نستهلك الذاكرة تقريبًا عند إنشاء قائمة إبطال الشهادات (CRL) - نحن بحاجة فقط إلى مكان للعمل مع تمثيل DER الخاص به: في هذه الحالة ، نحن نتحدث عن بضع عشرات ميغابايت (على عكس قائمة نصف غيغابايت من كائنات RevokeCertificate). ولكن هناك اختلاف في السلوك: يحدث فحص SEQUENCE OF / SET OF فقط بعد استنفاد المكرر ، وليس في لحظة تعيين قيمة.

ترميز DER المتدفق


إنه مستحيل. بعد كل شيء ، هذا هو DER - يجب معرفة أطوال جميع عناصر TLV (العلامة + الطول + القيمة) مسبقًا!

ولكن أود كثيرا! بعد كل شيء ، ما زلنا بحاجة إلى 10 غيغابايت من الذاكرة لتخزين تمثيل DER لنسخة قاعدة البيانات: raw = cms.encode () ! من الناحية المثالية ، أود أن أنقل كاتبًا معينًا حيث سيتم كتابة التمثيل المتسلسل. ربما قم بنقل واصف الملف ، اترك العناصر النائبة في الملف في مكان بالأطوال ثم املأها عن طريق البحث؟ لسوء الحظ ، فإن الطول (والعنصر النائب) على التوالي غير معروف مسبقًا.

تلقت PyDERASN إمكانية تشفير DER ثنائي التمرير. في الممر الأول ، يتم جمع المعرفة حول أطوال الأشياء ، مما يخلق حالة مؤقتة. والثاني هو الجريترميز DER في كاتب معين ، ممكن بالفعل بسبب معرفة الأطوال. لقد كان تنفيذ هذا الأمر بسيطًا ، حيث تم إضافة القليل من طرق التمريرين لكل نوع من أنواع ASN.1 الأساسية. بما أن اجتياز الأشياء محدد بدقة (D - مميز!) ، ثم ، لتخزين الأطوال اللازمة ، يتم الاحتفاظ بقائمة بسيطة ، حيث يتم اجتياز شجرة الكائنات بأكملها ، يتم إضافة قيم الطول. بالنسبة لبعض الأنواع ، يكون الطول ثابتًا. بالنسبة للبعض ، هناك حاجة فقط للإبلاغ عن حاوية المنبع ( SEQUENCE / SET ، SEQUENCE OF / SET OF ، EXPLICIT TAG ). على سبيل المثال ، تبدو حالة طول قائمة شهادتين ملغاة كما يلي:

revCert = RevokedCertificate((
    ("userCertificate", CertificateSerialNumber(123)),
    ("revocationDate", Time(("utcTime", UTCTime(datetime.utcnow())))),
))
revs = RevokedCertificates([revCert, revCert])

(42, [40, 18, 18])

في هذه الحالة ، نحتاج إلى معرفة طول القيمة فقط لكل من الشهادات المبطلة والقائمة بأكملها ككل. لا يتم تخزين طول الأعداد الصحيحة والوقت المشفر (في DER طول ثابت) في الحالة على أنها غير ضرورية. ونتيجة لذلك ، بالنسبة إلى CACert.org CRL ، تستغرق هذه القائمة أكثر من 3.5 MiB بقليل ، وبالنسبة إلى CMS العملاقة ، حيث يقع كل الوزن تقريبًا في حقل واحد مع نسخة من قاعدة البيانات ، يستغرق حوالي 0.5 KiB.

يتم إجراء ترميز بتمريرين بمكالمتين:

fulllen, state = obj.encode1st()
with open("result", "wb") as fd:
    obj.encode2nd(fd.write, iter(state))

يشير المرور الأول أيضًا إلى الطول الكامل للبيانات ، والذي يمكن استخدامه للتحقق من المساحة الحرة أو تخصيصها عن طريق بعض مكالمات posix_fallocate .

باستخدام وظيفة المساعد encode2pass (obj) ، يمكنك إجراء ترميز ثنائي الممر في الذاكرة. لماذا؟ يمكن أن يكون أكثر اقتصادا بكثير في استهلاك الذاكرة ، لأنه لن يقوم ، في حالة CACert.org CRL ، بتخزين 416k + خطوط ثنائية صغيرة مرتبطة بمكالمة b "". Join () . ومع ذلك ، يتطلب هذا المزيد من وقت المعالج ، لأنه يجب أن تسير جميع الكائنات مرتين.

الآن يمكننا ترميز CMS كبير بشكل تعسفي في DER ، عمليًا دون استهلاك الذاكرة. ولكن في حالة CRL ، استخدمنا منشئ إبطال الشهادات ، والذي سينفد بعد نهاية التمرير الأول. ماذا أفعل؟ مجرد إعادة تهيئة مرة أخرى!

_, state = crl.encode1st()
crl["tbsCertList"]["revokedCertificates"] = revCertsGenerator()
crl.encode2nd(writer, iter(state))

بالطبع ، نحن ملزمون بالتأكد من أن نتيجة المكرر ستكون هي نفسها تمامًا ، وإلا سنحصل على DER مكسور. إذا تم أخذ البيانات من مؤشر DBMS ، فلا تنسَ مستوى عزل المعاملات القابل للقراءة والفرز.

ترميز تيار حقيقي: CER


كما تعلم ، فإن DER (قواعد التشفير المميزة) هي مجموعة فرعية من BER (قواعد التشفير الأساسية) التي تنظم قواعد التشفير بشكل صارم بطريقة واحدة فقط. هذا يسمح باستخدامه في مهام التشفير. ولكن هناك مجموعة فرعية أخرى جديرة بالملاحظة من BER: CER (قواعد الترميز المتعارف عليها). مثل DER ، لديها تمثيل واحد محتمل للبيانات. يختلف CER عن DER في العديد من التفاصيل ، لكنها تسمح لك بإجراء ترميز دفق حقيقي للبيانات. لسوء الحظ ، لم تصبح CER شائعة مثل DER.

مع حذف الاختلافات غير الملحوظة (مثل علامات الفرز في SET) ، فإن CER لها اختلافان أساسيان عن DER:

  • (constructed, ) indefinite (LENINDEF PyDERASN). , SEQUENCE/SET, SEQUENCE OF/SET OF, EXPLICIT TAG- :

    TAG_CONSTRUCTED || LEN(VALUE) || VALUE
    

    LENINDEF (0x80) EOC ( , ) :

    TAG_CONSTRUCTED || 80 || VALUE || 00 00
    

  • *STRING-, 1000-, chunk- 1000-. , , DER. , 512 DER:

    TAG_PRIMITIVE || LEN(512) || 512B
    

    2048 :

    TAG_CONSTRUCTED || 80 ||
        TAG_PRIMITIVE || LEN(1000) || 1000B ||
        TAG_PRIMITIVE || LEN(1000) || 1000B ||
        TAG_PRIMITIVE || LEN(48) || 48B || 00 00
    

كل هذا (بالإضافة إلى بعض الأشياء الصغيرة) يسمح بالدفق (مع 1000 بايت مخزن مؤقت للسلاسل) لترميز أي كائنات. وبالمثل ، يمكنك استخدام mmap والمكرر. يتم ترميز CER ببساطة عن طريق استدعاء طريقة. encode_cer (كاتب) . لسوء الحظ ، لم تتمكن PyDERASN بعد من التحقق من صحة CER أثناء فك التشفير ، لذلك نحن مضطرون لفك تشفير البيانات كـ BER.

بالمناسبة ، يتطلب معيار CMS تشفيرًا في BER (كل من DER و CER ، تلقائي ، BER). لذلك ، يمكننا ترميز نسختنا الضخمة من قاعدة البيانات في CER CMS بدون تمرير DER. ومع ذلك ، مطلوب SignedData أن يكون عنصر SignedAttributes مشفرًا في DER ، كما هو الحال مع شهادة X.509الشهادات. يتيح لك PyDERASN فرض استخدام DER في بنيات معينة بمجرد إضافة السمة der_forced = True .

فك تشفير الدفق: وضع evgen


لقد تعلمنا الترميز ، ولكن فقط mmap سيساعد في فك الترميز . سيتطلب مفكك تشفير دفق "حقيقي" ، والذي يحتوي على مقابض تحكم في شكل "أعطني المزيد من البيانات" ، "أنت هنا" ، نوعًا ما من الحالة - يتطلب تغييرًا جذريًا في PyDERASN. وأنا شخصياً لا أرى أنه سيكون أكثر ملاءمة من الحل الحالي.

والحل الحالي بسيط للغاية. في عملية فك التشفير ، تظهر العديد من العناصر البدائية التي تم فك تشفيرها في أيدينا في الذاكرة ، منها يتم تجميع مكونات أعلى (مُنشأة) ، ومكونات أخرى ، وما إلى ذلك ... نقوم بتجميع الكائنات لجعلها مركبة ، والوصول إلى القمة تعطينا شيء واحد كبير. لماذا لا "نعطي" على الفور جميع أنواع فك الشفرةالأشياء ، بمجرد ظهورها على أيدينا؟ أي ، ليس لإرجاع كائن نهائي ، ولكن مولدًا يولد العديد من الكائنات التي تم فك تشفيرها. في الواقع ، في PyDERASN الآن أصبحت جميع طرق فك التشفير مولدات لمثل هذه "الأحداث" (جيل الحدث ، evgen).

إذا قمنا بتمكين وضع فك تشفير evgen الخاص بـ CACert.org CRL الضخم ، فسوف نرى الصورة التالية:

$ python -m pyderasn --schema tests.test_crl:CertificateList --evgen revoke.crl
[][T,L,  V len]
     10   [1,1,      1]   . . version: Version INTEGER v2 (01) OPTIONAL
     15   [1,1,      9]   . . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.13
     26   [0,0,      2]   . . . parameters: [UNIV 5] ANY OPTIONAL
     13   [1,1,     13]   . . signature: AlgorithmIdentifier SEQUENCE
     34   [1,1,      3]   . . . . . . type: AttributeType OBJECT IDENTIFIER 2.5.4.10
     39   [0,0,      9]   . . . . . . value: [UNIV 19] AttributeValue ANY
     32   [1,1,     14]   . . . . . 0: AttributeTypeAndValue SEQUENCE
     30   [1,1,     16]   . . . . 0: RelativeDistinguishedName SET OF

                                 [...]

    188   [1,1,      1]   . . . . userCertificate: CertificateSerialNumber INTEGER 17 (11)
    191   [1,1,     13]   . . . . . utcTime: UTCTime UTCTime 2003-04-01T14:25:08
    191   [0,0,     15]   . . . . revocationDate: Time CHOICE utcTime
    191   [1,1,     13]   . . . . . utcTime: UTCTime UTCTime 2003-04-01T14:25:08
    186   [1,1,     18]   . . . 0: RevokedCertificate SEQUENCE
    208   [1,1,      1]   . . . . userCertificate: CertificateSerialNumber INTEGER 20 (14)
    211   [1,1,     13]   . . . . . utcTime: UTCTime UTCTime 2002-10-01T02:18:01
    211   [0,0,     15]   . . . . revocationDate: Time CHOICE utcTime
    206   [1,1,     18]   . . . 1: RevokedCertificate SEQUENCE

                                 [...]

9144992   [0,0,     15]   . . . . revocationDate: Time CHOICE utcTime
9144985   [1,1,     20]   . . . 415755: RevokedCertificate SEQUENCE
    181   [1,4,9144821]   . . revokedCertificates: RevokedCertificates SEQUENCE OF OPTIONAL
      5   [1,4,9144997]   . tbsCertList: TBSCertList SEQUENCE
9145009   [1,1,      9]   . . algorithm: OBJECT IDENTIFIER 1.2.840.113549.1.1.13
9145020   [0,0,      2]   . . parameters: [UNIV 5] ANY OPTIONAL
9145007   [1,1,     13]   . signatureAlgorithm: AlgorithmIdentifier SEQUENCE
9145022   [1,3,    513]   . signatureValue: BIT STRING 4096 bits
      0   [1,4,9145534]  CertificateList SEQUENCE

  • في بداية فك التشفير ، رأينا علامة CertificateList SEQUENCE ، طول البيانات ، ولكن لم يعرف الكائن بعد ما إذا كان يمكن فك تشفيره حتى النهاية. حتى الآن نحن فقط في طور العمل عليها.
  • SEQUENCE: version, INTEGER. . , . ( 10)
  • signature, SEQUENCE- : algorithm parameters. OBJECT IDENTIFIER ANY . ( 15, 26)
  • , , signature SEQUENCE , , : . ( 13)
  • , RevokedCertificate . ( 186, 206, ..)
  • tbsCertList . ( 5)
  • CertificateList, SEQUENCE, , , . ( 0)

بالطبع ، كل * STRING والقوائم ( * OF ) لا تحمل معنى حقيقيًا. في حالة DER ، عند معرفة .offset و .vlen ، يمكنك قراءة قيمة السطر من ملف (قطعة من الذاكرة؟). يمكن جمع وتجميع الكائنات المتسلسلة حسب الحاجة ، أثناء تلقي جميع الأحداث.

مسار فك الشفرة و evgen_mode_upto


كيف نفهم أي نوع من الكائن، ما نوع من عدد صحيح لدينا في متناول اليد؟ لكل كائن ما يسمى بمسار فك التشفير الخاص به ، والذي يحدد بشكل فريد كائنًا معينًا في البنية. على سبيل المثال ، بالنسبة لأحداث مسار فك تشفير CACert.org CRL:

tbsCertList:version
tbsCertList:signature:algorithm
tbsCertList:signature:parameters
tbsCertList:signature
tbsCertList:issuer:rdnSequence:0:0:type
                                 [...]
tbsCertList:issuer:rdnSequence
tbsCertList:issuer
                                 [...]
tbsCertList:revokedCertificates:0:userCertificate
tbsCertList:revokedCertificates:0:revocationDate:utcTime
tbsCertList:revokedCertificates:0:revocationDate
tbsCertList:revokedCertificates:0
tbsCertList:revokedCertificates:1:userCertificate
tbsCertList:revokedCertificates:1:revocationDate:utcTime
tbsCertList:revokedCertificates:1:revocationDate
tbsCertList:revokedCertificates:1
                                 [...]
tbsCertList:revokedCertificates:415755:userCertificate
tbsCertList:revokedCertificates:415755:revocationDate:utcTime
tbsCertList:revokedCertificates:415755:revocationDate
tbsCertList:revokedCertificates:415755
tbsCertList:revokedCertificates
tbsCertList
signatureAlgorithm:algorithm
signatureAlgorithm:parameters
signatureAlgorithm
signatureValue

هذه هي الطريقة التي يمكننا من خلالها طباعة قائمة الأرقام التسلسلية لإبطال الشهادات من قائمة الشهادات الباطلة هذه:

raw = file_mmaped(open("....crl", "rb"))
for decode_path, obj, tail in CertificateList().decode_evgen(raw):
    if (len(decode_path) == 5) and (decode_path[-1] == "userCertificate"):
        print(int(obj))

يمكن أن تحتوي بنية RevokedCertificate على الكثير من المعلومات ، بما في ذلك ملحقات مختلفة. من الناحية التقنية البحتة ، نحصل على جميع البيانات حول الشهادة التي تم إبطالها في وضع evgen ، ولكن تجميع الأحداث المتعلقة بشهادة تم إبطالها ليس ملائمًا جدًا. نظرًا لأن كل شهادة نهائية تم إبطالها ، في الواقع ، لن تشغل مساحة كبيرة ، سيكون من الرائع أن يكون لديك كل نفس الشيء ، لا يتم "فرز" جميع الأشياء تمامًا في الأحداث. يسمح PyDERASN للقائمة بتحديد مسارات فك التشفير التي يتم فيها تعطيل وضع evgen. حتى نتمكن من تعيين مسار فك الشفرة (أي عنصر من قائمة ("tbsCertList" ، "إبطال الشهادات") ) التي نريد استلام كائن RevokedCertificate الكامل عليها :

for decode_path, obj, _ in CertificateList().decode_evgen(raw, ctx={
    "evgen_mode_upto": (
        (("tbsCertList", "revokedCertificates", any), True),
    ),
}):
    if (len(decode_path) == 3) and (decode_path[1] == "revokedCertificates"):
        print(int(obj["userCertificate"]))

سلاسل التجميع: agg_octet_string


الآن ليس لدينا مشاكل في فك تشفير الأشياء بأي حجم. لا توجد مشكلة في فك تشفير CMS المرمزة بتقنية DER مع نسخة من قاعدة البيانات أيضًا: نحن في انتظار حدث بمسار فك تشفير يشير إلى البيانات الموقعة / المشفرة في CMS ومعالجة البيانات من الملف باستخدام offset + vlen. ولكن ماذا لو كان CMS بتنسيق CER؟ ثم لن يساعد الإزاحة + vlen ، حيث يتم تقسيم جميع وحدات 10 GiB الخاصة بنا إلى أجزاء من 1000 بايت ، والتي بينها رأس DER. ولكن ماذا لو كان لدينا BER يمكن أن يكون تداخل * STRING فيه أي شيء؟

SOME STRING[CONSTRUCTED]
    OCTET STRING[CONSTRUCTED]
        OCTET STRING[PRIMITIVE]
            DATA CHUNK
        OCTET STRING[PRIMITIVE]
            DATA CHUNK
        OCTET STRING[PRIMITIVE]
            DATA CHUNK
    OCTET STRING[PRIMITIVE]
        DATA CHUNK
    OCTET STRING[CONSTRUCTED]
        OCTET STRING[PRIMITIVE]
            DATA CHUNK
        OCTET STRING[PRIMITIVE]
            DATA CHUNK
    OCTET STRING[CONSTRUCTED]
        OCTET STRING[CONSTRUCTED]
            OCTET STRING[PRIMITIVE]
                DATA CHUNK

عند فك التشفير في وضع evgen ، نحصل على كل حدث من الأحداث مقابل كل قطعة ويكفي لنا أن نجمع أحداثًا بدائية فقط (غير مبنية) * STRING ، حيث تحتوي الإزاحة + vlen على أجزاء حقيقية من البيانات. PyDERASN لديه وظيفة مساعد ملائمة agg_octet_string التي تقوم بذلك. يكفيها أن تجتاز مولد حدث ، مسار فك الشفرة "أدناه" الذي من الضروري تجميع سلسلة ، بيانات ثنائية (أو عرض ذاكرة ) وكاتب - وظيفة يتم استدعاؤها مع كل قطعة من البيانات المستلمة. نريد حساب تجزئة SHA512 وفي نفس الوقت حفظ محتويات encapContentInfo.eContent CMS؟ ابحث عن موقع حقل المحتوى (الذي سيقع فيه SignedData) ، ثم فك تشفير محتويات CER الخاصة به ، والكتابة في وقت واحد إلى FS وتجزئة:

fdIn = open("data.p7m", "rb")
raw = file_mmaped(fdIn)
for decode_path, obj, _ in ContentInfo().decode_evgen(raw, ctx={"bered": True}):
    if decode_path == ("content",):
        content = obj
        break
hasher_state = sha512()
fdOut = open("dump.sql.zst", "wb")
def hash_n_save(data):
    write_full(fdOut, data)
    hasher_state.update(data)
    return len(data)
evgens = SignedData().decode_evgen(
    raw[content.offset:],
    offset=content.offset,
    ctx={"bered": True},
)
agg_octet_string(evgens, ("encapContentInfo", "eContent"), raw, hash_n_save)

هنا ، يتم استخدام أداة كتابة مكتوبة أخرى ، والتي تستدعي الكاتب حتى تتم كتابة جميع البيانات ، لأنه بشكل عام ، عند الكتابة إلى ملف ، لا يلزم نظام التشغيل لمعالجة جميع البيانات المنقولة وتحتاج إلى متابعة العملية حتى تتم كتابتها بالكامل.

زوجان من المحبة عن SET OF


من الناحية التقنية البحتة ، لا يمكن ترميز SET OF بشكل فوري في ترميزات DER و CER ، حيث يجب فرز التمثيلات المشفرة لجميع العناصر. لا CER ولا DER بتمريرين سيساعدون هنا. وبالتالي لا يوصي معيار ASN.1 الحديث باستخدام كل من SET (يتطلب الفرز المماثل في DER) و SET OF .

وما هذه الصورة في بداية المقال؟


ظهر في PyDERASN متصفح ASN.1 تفاعلي بسيط ، وهو ما ساعدني شخصياً عدة مرات على كتابة معالجات للهياكل المعقدة. يسمح لك بالتجول في البنية التي تم فك تشفيرها بالكامل ، مع إظهار التفاصيل الكاملة حول كل كائن وموقعه في البيانات الثنائية ومسار فك الترميز. بالإضافة إلى ذلك ، يمكن حفظ أي عنصر في ملف منفصل ، مثل الشهادات أو CRLs المضمنة في CMS.

سيرجي ماتفييف ، cipherpunk ، Python / Go-developer ، كبير المتخصصين في FSUE "المركز العلمي والتقني" أطلس ".

All Articles