المجموعة 3
هذه هي المجموعة التالية من تحديات تشفير شيفرات الكتل (block cipher cryptography) (حتى أمور العشوائية هنا تخدم تشفير شيفرات الكتل).
هذه المجموعة متوسطة الصعوبة. تتضمن هجومًا شهيرًا على وضع CBC، وهجوم «استنساخ» على مولّد أرقام عشوائية شائع قد يكون من المزعج إتقانه.
وقد وصلنا أيضًا في تحديات التشفير إلى نقطة تكون فيها جميع التحديات، باستثناء واحد محتمل، قيّمة في كسر التشفير الواقعي.
17. أوراكل حشو CBC
هذا أشهر هجوم على تشفير شيفرات الكتل الحديثة.
اجمع شيفرة الحشو (padding) وشيفرة CBC لكتابة دالتين.
ينبغي أن تختار الدالة الأولى عشوائيًا واحدة من السلاسل العشر التالية:
MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=
MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=
MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==
MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==
MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl
MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==
MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==
MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=
MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=
MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93
... وأن تولّد مفتاح AES عشوائيًا (ينبغي أن تحفظه لكل عمليات التشفير المستقبلية)، وتحشو السلسلة إلى حجم كتلة AES البالغ 16 بايت وتشفّرها بـ CBC تحت ذلك المفتاح، وتقدّم للمستدعي النص المشفَّر ومتجه التهيئة (IV).
ينبغي أن تستهلك الدالة الثانية النص المشفَّر الذي تنتجه الدالة الأولى، وتفك تشفيره، وتتحقق من حشوه، وتعيد true أو false بناءً على صلاحية الحشو.
ما الذي تفعله هنا.
هذا الزوج من الدوال يحاكي تشفير AES-CBC كما يُنشر على الخادم في تطبيقات الويب؛ والدالة الثانية تحاكي استهلاك الخادم لرمز جلسة مشفَّر، كما لو كان كوكيز.
واتضح أنه من الممكن فك تشفير النصوص المشفَّرة التي تنتجها الدالة الأولى.
يعتمد فك التشفير هنا على تسرّب عبر قناة جانبية من دالة فك التشفير. التسرّب هو رسالة الخطأ التي تفيد بصلاحية الحشو أو عدمها.
يمكنك أن تجد مئة صفحة ويب تشرح كيف يعمل هذا الهجوم، لذا لن أعيد شرحه. ما سأقوله هو هذا:
الرؤية الأساسية وراء هذا الهجوم هي أن البايت 01h حشو صحيح، ويحدث في 1 من 256 تجربة من النصوص الصريحة «العشوائية» الناتجة عن فك تشفير نص مشفَّر مُتلاعَب به.
أما 02h منفردًا فليس حشوًا صحيحًا.
و02h 02h حشو صحيح، لكنه أقل احتمالًا بكثير للحدوث عشوائيًا من 01h.
و03h 03h 03h أقل احتمالًا حتى من ذلك.
لذا يمكنك أن تفترض أنه إن أفسدت عملية فك تشفير وكان حشوها صحيحًا، فأنت تعرف ما بايت الحشو ذلك.
من السهل أن تتعثر بحقيقة أن النصوص الصريحة في CBC «محشوّة». لا علاقة لأوراكلات الحشو بالحشو الفعلي لنص صريح CBC. إنه هجوم يستهدف قطعة شيفرة محددة تتولى فك التشفير. يمكنك تنصيب أوراكل حشو على أي كتلة CBC، سواء كانت محشوّة أم لا.
18. تنفيذ CTR، وضع شيفرة التيار
السلسلة:
L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syLXzhPweyyMTJULu/6/kXX0KSvoOLSFQ==
... تُفك تشفيرها إلى شيء يقارب الإنجليزية في وضع CTR، وهو وضع لشيفرة كتل AES يحوّل AES إلى شيفرة تيار (stream cipher)، بالمعطيات التالية:
key=YELLOW SUBMARINE
nonce=0
format=64 bit unsigned little endian nonce,
64 bit little endian block count (byte count / 16)
وضع CTR بسيط جدًا.
بدلًا من تشفير النص الصريح، يشفّر وضع CTR عدّادًا جاريًا، منتجًا كتلة من 16 بايت من تيار المفاتيح (keystream)، تُدمج بـ XOR مع النص الصريح.
على سبيل المثال، لأول 16 بايت من رسالة بهذه المعطيات:
keystream = AES("YELLOW SUBMARINE",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
... وللـ16 بايت التالية:
keystream = AES("YELLOW SUBMARINE",
"\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00")
... ثم:
keystream = AES("YELLOW SUBMARINE",
"\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00")
لا يتطلب وضع CTR حشوًا؛ عندما ينفد النص الصريح، تتوقف ببساطة عن دمج تيار المفاتيح بـ XOR وعن توليده.
فك التشفير مطابق للتشفير. ولّد تيار المفاتيح نفسه، وادمجه بـ XOR، واستعد النص الصريح.
فك تشفير السلسلة الموجودة في أعلى هذه الدالة، ثم استخدم دالة CTR الخاصة بك لتشفير وفك تشفير أشياء أخرى.
هذا هو وضع شيفرة الكتل الوحيد المهم في الشيفرة الجيدة.
تعتمد معظم التشفير الحديث على وضع CTR لتكييف شيفرات الكتل مع شيفرات التيار، لأن معظم ما نريد تشفيره يوصف بشكل أفضل كتيار لا كسلسلة كتل. قال دانيال بيرنشتاين مرة مازحًا لفيل روغاواي إن أنظمة التشفير الجيدة لا تحتاج تحويلات «فك التشفير». تراكيب مثل CTR هي ما كان يقصده.
19. كسر وضع CTR ذي القيمة العشوائية الوحيدة الثابتة باستخدام الاستبدالات
خذ دالة تشفير/فك تشفير CTR الخاصة بك وثبّت قيمة nonce على 0. ولّد مفتاح AES عشوائيًا.
في عمليات تشفير متتالية (لا في تيار CTR واحد كبير جارٍ)، شفّر كل سطر من فك ترميز base64 للأسطر التالية، منتجًا نصوصًا مشفَّرة مستقلة متعددة:
SSBoYXZlIG1ldCB0aGVtIGF0IGNsb3NlIG9mIGRheQ==
Q29taW5nIHdpdGggdml2aWQgZmFjZXM=
RnJvbSBjb3VudGVyIG9yIGRlc2sgYW1vbmcgZ3JleQ==
RWlnaHRlZW50aC1jZW50dXJ5IGhvdXNlcy4=
SSBoYXZlIHBhc3NlZCB3aXRoIGEgbm9kIG9mIHRoZSBoZWFk
T3IgcG9saXRlIG1lYW5pbmdsZXNzIHdvcmRzLA==
T3IgaGF2ZSBsaW5nZXJlZCBhd2hpbGUgYW5kIHNhaWQ=
UG9saXRlIG1lYW5pbmdsZXNzIHdvcmRzLA==
QW5kIHRob3VnaHQgYmVmb3JlIEkgaGFkIGRvbmU=
T2YgYSBtb2NraW5nIHRhbGUgb3IgYSBnaWJl
VG8gcGxlYXNlIGEgY29tcGFuaW9u
QXJvdW5kIHRoZSBmaXJlIGF0IHRoZSBjbHViLA==
QmVpbmcgY2VydGFpbiB0aGF0IHRoZXkgYW5kIEk=
QnV0IGxpdmVkIHdoZXJlIG1vdGxleSBpcyB3b3JuOg==
QWxsIGNoYW5nZWQsIGNoYW5nZWQgdXR0ZXJseTo=
QSB0ZXJyaWJsZSBiZWF1dHkgaXMgYm9ybi4=
VGhhdCB3b21hbidzIGRheXMgd2VyZSBzcGVudA==
SW4gaWdub3JhbnQgZ29vZCB3aWxsLA==
SGVyIG5pZ2h0cyBpbiBhcmd1bWVudA==
VW50aWwgaGVyIHZvaWNlIGdyZXcgc2hyaWxsLg==
V2hhdCB2b2ljZSBtb3JlIHN3ZWV0IHRoYW4gaGVycw==
V2hlbiB5b3VuZyBhbmQgYmVhdXRpZnVsLA==
U2hlIHJvZGUgdG8gaGFycmllcnM/
VGhpcyBtYW4gaGFkIGtlcHQgYSBzY2hvb2w=
QW5kIHJvZGUgb3VyIHdpbmdlZCBob3JzZS4=
VGhpcyBvdGhlciBoaXMgaGVscGVyIGFuZCBmcmllbmQ=
V2FzIGNvbWluZyBpbnRvIGhpcyBmb3JjZTs=
SGUgbWlnaHQgaGF2ZSB3b24gZmFtZSBpbiB0aGUgZW5kLA==
U28gc2Vuc2l0aXZlIGhpcyBuYXR1cmUgc2VlbWVkLA==
U28gZGFyaW5nIGFuZCBzd2VldCBoaXMgdGhvdWdodC4=
VGhpcyBvdGhlciBtYW4gSSBoYWQgZHJlYW1lZA==
QSBkcnVua2VuLCB2YWluLWdsb3Jpb3VzIGxvdXQu
SGUgaGFkIGRvbmUgbW9zdCBiaXR0ZXIgd3Jvbmc=
VG8gc29tZSB3aG8gYXJlIG5lYXIgbXkgaGVhcnQs
WWV0IEkgbnVtYmVyIGhpbSBpbiB0aGUgc29uZzs=
SGUsIHRvbywgaGFzIHJlc2lnbmVkIGhpcyBwYXJ0
SW4gdGhlIGNhc3VhbCBjb21lZHk7
SGUsIHRvbywgaGFzIGJlZW4gY2hhbmdlZCBpbiBoaXMgdHVybiw=
VHJhbnNmb3JtZWQgdXR0ZXJseTo=
QSB0ZXJyaWJsZSBiZWF1dHkgaXMgYm9ybi4=
(هذا ينبغي أن ينتج 40 نصًا مشفَّرًا قصيرًا بـ CTR).
لأن قيمة nonce في CTR لم تكن عشوائية لكل تشفير، فقد شُفّر كل نص مشفَّر مقابل تيار المفاتيح نفسه. هذا سيئ جدًا.
بعد إدراك ذلك، وكما في معظم شيفرات التيار (بما فيها RC4، وأي شيفرة كتل تُشغَّل بوضع CTR بوضوح)، فإن «التشفير» الفعلي لبايت من البيانات لا يعدو عملية XOR واحدة، فينبغي أن يكون واضحًا أن:
CIPHERTEXT-BYTE XOR PLAINTEXT-BYTE = KEYSTREAM-BYTE
وبما أن تيار المفاتيح هو نفسه لكل نص مشفَّر:
CIPHERTEXT-BYTE XOR KEYSTREAM-BYTE = PLAINTEXT-BYTE (ie, "you don't
say!")
هاجم هذا النظام التشفيري قطعة قطعة: خمّن الحروف، واستخدم تكرار اللغة الإنجليزية المتوقع للتحقق من التخمينات، والتقط ثلاثيات الحروف الإنجليزية الشائعة، وهكذا.
لا تفرط في التفكير.
هناك نقاط لأتمتة هذا، لكن جزءًا من سبب جعلي إياك تفعله هو اعتقادي أن هذا الأسلوب دون المستوى الأمثل.
20. كسر CTR ذي القيمة العشوائية الوحيدة الثابتة إحصائيًا
في هذا الملف ستجد مجموعة مشابهة من النصوص الصريحة المُرمَّزة بـ Base64. افعل بها تمامًا ما فعلته بالأولى، لكن حُلّ المسألة بطريقة مختلفة.
بدلًا من تخمينات موضعية لنص صريح معروف، عامل مجموعة النصوص المشفَّرة كما تعامل XOR متكرر المفتاح.
من الواضح أن تشفير CTR يبدو مختلفًا عن XOR متكرر المفتاح، لكن مع قيمة nonce ثابتة هما الشيء نفسه فعليًا.
لاستغلال ذلك: خذ مجموعة نصوصك المشفَّرة واقتطعها إلى طول مشترك (طول أصغر نص مشفَّر سيفي بالغرض).
حُلّ التسلسل الناتج من النصوص المشفَّرة كما لو كان XOR متكرر المفتاح، بحجم مفتاح يساوي طول النص المشفَّر الذي دمجته بـ XOR.
21. تنفيذ مولّد الأرقام العشوائية MT19937 Mersenne Twister
يمكنك الحصول على الشيفرة الزائفة لهذا من ويكيبيديا.
إن كنت تكتب بـ Python أو Ruby أو (للأسف) PHP، فمن المرجح أن لغتك تمنحك MT19937 أصلًا باسم "rand()"؛ لا تستخدم rand(). اكتب المولّد بنفسك.
22. كسر بذرة MT19937
تأكد من أن MT19937 الخاص بك يقبل قيمة بذرة (seed) صحيحة. اختبره (تحقق من حصولك على التسلسل نفسه من المخرجات عند بذرة معينة).
اكتب روتينًا ينفّذ العملية التالية:
- انتظر عددًا عشوائيًا من الثواني بين، لا أعرف، 40 و1000.
- ابدأ المولّد ببذرة من الطابع الزمني الحالي لنظام Unix
- انتظر عددًا عشوائيًا من الثواني مرة أخرى.
- أعِد أول مخرج 32 بتًا من المولّد.
فهمت الفكرة. اذهب لتناول القهوة أثناء تشغيله. أو حاكِ مرور الوقت فقط، وإن كنت ستفوّت بعض متعة هذا التمرين إن فعلت ذلك.
من مخرج المولّد ذي 32 بتًا، اكتشف البذرة.
23. استنساخ مولّد MT19937 من مخرجاته
تتكون الحالة الداخلية لـ MT19937 من 624 عددًا صحيحًا بطول 32 بتًا.
لكل دفعة من 624 مخرجًا، يبدّل MT حالته الداخلية. وبتدوير الحالة بانتظام، يحقق MT19937 دورة مقدارها 2**19937، وهو رقم كبير.
في كل مرة يُقرَع فيها MT19937، يخضع عنصر من حالته الداخلية لدالة طبع (tempering) تنشر البتّات في النتيجة.
دالة الطبع قابلة للعكس؛ يمكنك كتابة دالة «نزع الطبع» (untemper) تأخذ مخرج MT19937 وتحوّله مرة أخرى إلى العنصر المقابل في مصفوفة حالة MT19937.
لعكس تحويل الطبع، طبّق معكوس كل عملية من عمليات تحويل الطبع بترتيب معاكس. هناك نوعان من العمليات في تحويل الطبع، كل منهما مطبَّق مرتين؛ إحداهما XOR مع قيمة مُزاحة لليمين، والأخرى XOR مع قيمة مُزاحة لليسار بعد دمجها بعملية AND مع عدد سحري. لذا ستحتاج إلى شيفرة لعكس عمليتي «اليمين» و«اليسار».
بمجرد أن يعمل «نزع الطبع»، أنشئ مولّد MT19937 جديدًا، واقرعه للحصول على 624 مخرجًا، وانزع الطبع من كل منها لإعادة إنشاء حالة المولّد، وألصق تلك الحالة في نسخة جديدة من مولّد MT19937.
ينبغي أن يتنبأ المولّد «المُلصَّق» الجديد بقيم المولّد الأصلي.
توقف وفكّر لحظة.
كيف تعدّل MT19937 لتجعل هذا الهجوم صعبًا؟ ماذا سيحدث لو أخضعت كل مخرج مطبوع لعملية تجزئة (hash) تشفيرية؟
24. إنشاء شيفرة تيار MT19937 وكسرها
يمكنك إنشاء شيفرة تيار بدائية من أي مولّد أعداد شبه عشوائية (PRNG)؛ استخدمه لتوليد تسلسل من مخرجات 8 بتات وسمِّ هذه المخرجات تيار مفاتيح. ادمج كل بايت من النص الصريح بـ XOR مع كل بايت متتالٍ من تيار المفاتيح.
اكتب الدالة التي تفعل ذلك لـ MT19937 باستخدام بذرة 16 بتًا. تحقق من قدرتك على التشفير وفك التشفير بشكل صحيح. ينبغي أن تبدو هذه الشيفرة مشابهة لشيفرة CTR الخاصة بك.
استخدم دالتك لتشفير نص صريح معروف (لنقل 14 محرف 'A' متتاليًا) مسبوق بعدد عشوائي من المحارف العشوائية.
من النص المشفَّر، استعد «المفتاح» (البذرة ذات 16 بتًا).
استخدم الفكرة نفسها لتوليد «رمز إعادة تعيين كلمة المرور» عشوائي باستخدام MT19937 مبذور من الوقت الحالي.
اكتب دالة للتحقق مما إذا كان أي رمز كلمة مرور معطى ناتجًا فعليًا عن مولّد MT19937 مبذور بالوقت الحالي.