شيفرات التيار
شيفرات التيار
الوصف
شيفرة التيار (stream cipher) هي خوارزمية تشفير بمفتاح متماثل (symmetric-key encryption) تشفّر تدفّقًا من البتّات. وفي الحالة المثلى يمكن أن يكون ذلك التدفّق
طويلًا كما نشاء؛ لكنّ شيفرات التيار في العالم الحقيقي لها حدود، وهي في العادة
كافية بما يكفي ألّا تمثّل مشكلة عملية.
محاولة ساذجة بشيفرات الكتل
لنحاول أن نبني شيفرة تيار بالأدوات التي لدينا أصلًا. وبما أنّ لدينا شيفرات كتل، فإنا نستطيع ببساطة تقسيم تدفّق وارد إلى كتل مختلفة، ثمّ تشفير كلّ كتلة:
يُسمَّى هذا النظام وضع ECB (ECB mode، أي Electronic Code Book Mode)، وهو إحدى
الطرق العديدة التي يمكن بها استعمال شيفرات الكتل لبناء شيفرات تيار. وللأسف،
فعلى الرغم من شيوعه الواسع في الأنظمة التشفيرية المنزلية، فإنّه يعاني عيوبًا أمنية
بالغة الخطورة. فمثلًا، في وضع ECB، تُسقَط كتل الدخل المتطابقة دائمًا على كتل خرج
متطابقة:
للوهلة الأولى، قد لا يبدو هذا مشكلة بالغة الخطورة. فبافتراض أنّ شيفرة الكتل آمنة، فلا يبدو أنّ المهاجم سيكون قادرًا على فكّ تشفير أيّ شيء. وبعد تقسيم تدفّق النصّ المشفَّر إلى كتل، لن يتمكّن المهاجم إلّا من ملاحظة أنّ كتلة نصّ مشفَّر — وبالتالي كتلة نصّ صريح — قد تكرّرت.
سنوضّح الآن عيوب وضع ECB الكثيرة بواسطة هجومين. أوّلًا، سنستغلّ الحقيقة القائلة
بأنّ تكرار كتل النصّ الصريح يؤدّي إلى تكرار كتل النصّ المشفَّر، عبر فحص بصريّ لصورة
مشفَّرة. ثمّ سنبيّن أنّ المهاجمين يستطيعون في كثير من الأحيان فكّ تشفير الرسائل
المشفَّرة في وضع ECB عبر التواصل مع الشخص الذي أجرى التشفير.
الفحص البصريّ لتدفّق مشفَّر
لإثبات أنّ هذه مشكلة بالغة الخطورة فعلًا، سنستعمل شيفرة كتل محاكاة بأحجام كتل متنوّعة ونطبّقها على صورة [1]. ثمّ نفحص المخرجات المختلفة فحصًا بصريًّا.

صورة النصّ الصريح، 2000 × 1400 بكسل، وعمق ألوان 24 بتًّا.

نصّ مشفَّر بوضع ECB، حجم كتلة 5 بكسلات (120 بتًّا).

نصّ مشفَّر بوضع ECB، حجم كتلة 30 بكسلًا (720 بتًّا).

نصّ مشفَّر بوضع ECB، حجم كتلة 100 بكسل (2400 بتًّا).

نصّ مشفَّر بوضع ECB، حجم كتلة 400 بكسل (9600 بتًّا).

النصّ المشفَّر تحت تشفير مثاليّ.
صورة النصّ الصريح مع صور النصّ المشفَّر تحت تشفير مثاليّ وتحت تشفير وضع ECB
بأحجام كتل متنوّعة. ومن الواضح أنّ معلومات عن البنية الكبرى للصورة تتسرّب. ويصبح
هذا الأثر أقلّ وضوحًا مع ازدياد أحجام الكتل، لكنّه لا يصبح كذلك إلّا عند أحجام
كتل أكبر بكثير من أحجام شيفرات الكتل المعتادة. فحجم الكتلة الأوّل
(fig-ECBDemoIdealizedCiphertext، أي حجم كتلة 5 بكسلات أو 120 بتًّا) وحده هو
الحجم الواقعيّ.
لأنّ كتل البكسلات المتطابقة في النصّ الصريح تُسقَط على كتل بكسلات متطابقة في النصّ المشفَّر، فإنّ البنية العامة للصورة تبقى محفوظة إلى حدٍّ بعيد.
وكما ترى، يبدو الوضع يتحسّن قليلًا مع أحجام الكتل الأكبر، لكنّ المشكلة الجوهريّة
تبقى قائمة: فالبنية الكبرى للصورة تبقى مرئية في جميع أحجام الكتل إلّا في الأكثر
تطرّفًا. وفضلا على ذلك، فإنّ جميع أحجام الكتل هذه إلّا الأصغر منها تكون كبيرة
بشكل غير واقعيّ. وبالنسبة إلى خريطة بتّات غير مضغوطة بثلاث قنوات لونية بعمق 8 بتّات،
يستهلك كلّ بكسل 24 بتًّا للتخزين. وبما أنّ حجم الكتلة في AES هو 128 بتًّا فقط،
فإنّ ذلك يعادل \frac{128}{24} أي أكثر قليلًا من 5 بكسلات لكلّ كتلة. وهذا عدد
بكسلات لكلّ كتلة أقلّ بكثير من أحجام الكتل الأكبر في المثال. لكنّ AES هي فرس العمل
في شيفرات الكتل الحديثة — ولا يمكن أن تكون هي مصدر الخلل، وليس السبب على الإطلاق هو
نقص حجم الكتلة.
لاحظ أنّ نظام تشفير مثاليّ يبدو كأنه ضجيج عشوائيّ. و«الانّه يشبه الضجيج العشوائيّ» لا يعني أنّ شيئًا مشفَّر على نحو صحيح: إنّما يعني فقط أنّنا لا نستطيع فحصه بطرق بسيطة.
هجوم آلة التشفير
في القسم السابق، ركّزنا على كيفية فحص مهاجم لنصّ مشفَّر بـوضع ECB. ويُسمَّى ذلك
هجومًا خاملًا (passive) على النصّ المشفَّر وحده. وهو خامل لأنّ المهاجم لا يتدخّل
في الاتصالات، وإنّما يفحص النصّ المشفَّر فحسب. أمّا في هذا القسم فندرس هجومًا
مختلفًا، نشطًا (active)، يتبادل فيه المهاجم رسائل مع ضحيّته. وسنرى كيف يتيح
الهجوم النشط للمهاجم فكّ تشفير نصوص مشفَّرة بـوضع ECB.
ولتحقيق ذلك، نقدّم مفهومًا جديدًا يُسمّى الآلة (oracle). وتُستعمل الآلات
(oracle) المعرَّفة رسميًّا في مجال علوم الحاسوب. ويكفينا لأغراضنا القول إنّ الآلة
تحسب دالة بعينها.
وفي حالتنا، تؤدّي الآلة عملية تشفير بعينها للمهاجم بوصفها آلة تشفير (encryption
oracle). فمعطى بعض البيانات A التي يختارها المهاجم، تشفّر الآلة تلك البيانات يتبعها
لاحقة سرّية S، في وضع ECB. أو، بالرموز:
C = ECB(E_k, A \| S)
الاحقة السرّية S خاصة بهذا النظام. وهدف المهاجم هو فكّ تشفيرها. والقدرة على
تشفير رسائل أخرى تتيح، على نحو مفاجئ، للمهاجم فكّ تشفير تلك اللاحقة. وقد تبدو هذه
الآلة مصطنعة، لكنّها شائعة في الممارسة العملية إلى حدٍّ كبير. ومن الأمثلة البسيطة
كعكة (cookie) مشفَّرة بوضع ECB، حيث يستطيع المهاجم التحكّم في البادئة A مثل حقل
اسم أو حقل عنوان بريد إلكترونيّ.
ترى لماذا يهمّ مفهوم الآلة هنا: فلن يكون في مقدور المهاجم حساب C بنفسه، إذ لا
يصل إلى مفتاح التشفير k ولا إلى اللاحقة السرّية S. وهدف الآلة أن تبقى تلك
القيم سرّية، لكنّنا سنرى كيف يتمكّن المهاجم من استعادة اللاحقة السرّية S (وليس
المفتاح k) على أيّ حال. يفعل ذلك بفحص النصّ المشفَّر C لقيم كثيرة مختارة بعناية
من البادئة A التي يختارها المهاجم.
قد يبدو افتراض وصول المهاجم إلى آلة كهذه افتراضًا مصطنعًا. لكن في الممارسة العملية
يمكن خداع كثير من البرمجيات لتتصرّف على هذا النحو. وحتى إن لم يستطع المهاجم التحكّم
في البرمجية الحقيقية بدقّة الاستعلام عن آلة، فإنّه لن يكون مُصطَدًا. فالوقت في صالحه:
لا عليه إلّا أن يقنع البرمجية بأن تعطي الجواب الذي يريده مرّة واحدة. والأنظمة التي
يكون فيها جزء من الرسالة سرّيًا وجزء آخر منها قابلًا للتأثير من المهاجم شائعة
جدًّا، وللأسف فإنّ وضع ECB كذلك شائع جدًّا.
فكّ تشفير كتلة باستعمال الآلة
يبدأ المهاجم بإرسال نصّ صريح A أقصر ببايت واحد من حجم الكتلة. وهذا يعني أنّ
الكتلة التي ستُشفَّر تتكوّن من تلك البايتات، مضافًا إليها البايت الأوّل من S،
والذي يمكننا تسميته s_0. ويحفظ المهاجم الكتلة المشفَّرة. فهو لا يعرف قيمة
s_0، لكنّه يعرف قيمة الكتلة المشفَّرة الأولى: E_k(A \| s_0). وفي الرسم، هذه
هي الكتلة C_{R1}:
ثمّ يجرّب المهاجم جميع القيم الممكنة للبايت الأخير في كتلة كاملة الحجم. وفي نهاية
الأمر يجد قيمة s_0؛ إذ يكون التخمين صحيحًا لأنّ الكتلة المشفَّرة الناتجة تطابق
الكتلة المشفَّرة C_{R1} التي حُفظت في وقت سابق.
ويمكن للمهاجم أن يكرّر هذه الاستراتيجية مع البايت ما قبل الأخير. فيُرسَل نصّ صريح
A أقصر ببايتين من حجم الكتلة. فتشفّر الآلة كتلة أولى تحوي A يتبعها البايتان
الأوّلان من اللاحقة السرّية، أي s_0s_1. ويحفظ المهاجم الكتلة.
وبما أنّ المهاجم يعرف s_0 أصلًا، فإنّ التخمين يبدأ من :math:A \| s_0 متبوعًا
بجميع القيم الممكنة لـs_1. وفي نهاية المطاف تصحّ تخمينات المهاجم، فتتطابق كتل
النصّ المشفَّر:
وهكذا يكرّر المهاجم الخطوات حتى يفكّ تشفير كتلة كاملة. وتتيح هذه الاستراتيجية تفريغ
كتلة بالقوة الغاشمة في p \cdot b محاولة، حيث p هو عدد القيم الممكنة لكلّ بايت
(مثلًا، بالنسبة إلى البايتات ذات الثمانية بتّات فإنّ ذلك 2^8 = 256)، وb هو
حجم الكتلة. وهذا الأسلوب المذكور أعلاه أفضل من هجوم القوة الغاشمة المعتاد الذي
يجرّب فيه المهاجم جميع الكتل الممكنة، وهو:
وبالنسبة إلى حجم كتلة معتاد قدره 16 بايتًا (أي 128 بتًّا)، فإنّ التفريغ بالقوة
الغاشمة يعني تجريب 256^{16} تركيبة. ويبلغ عدد المحاولات عددًا هائلًا من 39 رقمًا.
وهو كبير إلى حدٍّ يجعل تجريب جميع التركيبات مستحيلًا. وآلة التشفير encryption oracle في وضع ECB تتيح للمهاجم فكّ التشفير في 256 \cdot 16 = 4096 محاولة على
الأقصى، وهو عدد يمكن إدارته بسهولة أكبر بكثير.
الخلاصة
في العالم الحقيقي، تُستعمل شيفرات الكتل في أنظمة تشفّر كميات كبيرة من البيانات في
كلّ وقت. وقد رأينا أنّه عند استعمال وضع ECB، يحلّل المهاجم النصوص المشفَّرة ليعرف
الأنماط المتكرّرة، بل ويفكّ تشفير الرسائل أيضًا إن توفّر له وصول إلى آلة تشفير
(encryption oracle).
وحتى مع استعمالنا شيفرات كتل مثالية ذات خصائص غير واقعية، مثل أحجام كتل تتجاوز الألف بتّ، يبقى بإمكان المهاجم فكّ تشفير النصوص المشفَّرة. فشيفرات الكتل في العالم الحقيقي لها قيود أكثر من أمثلتنا المثالية، مثل أحجام كتل أصغر بكثير.
ولم نأخذ بعدُ في الحسبان أيّ نقاط ضعف محتملة في شيفرة الكتل. فليس AES ولا شيفرات الكتل الاختبارية هي ما يسبّب المشكلة، بل إنّ بناء ECB الذي استعملناه هو السبب. ومن الواضح أنّنا بحاجة إلى شيء أفضل.
أوضاع تشغيل شيفرات الكتل
إنّ إحدى الطرق الشائعة لإنتاج شيفرة تيار هي استعمال شيفرة كتل في تكوين
معيّن. ويتصرّف النظام المركّب وكأنّه شيفرة تيار. وتُسمَّى هذه التكوينات
وضع التشغيل (mode of operation)\s. وهي ليست خاصّة بشيفرة كتل بعينها.
أمّا وضع ECB الذي رأيناه توًّا، فهو أبسط وضع تشغيل من هذا النوع. وتحمل
الحروف ECB معنى «الكتاب الإلكتروني الشيفري» (electronic code book) [2]. وللأسباب
التي ناقشناها من قبل، فإنّ وضع ECB غير آمن. ولحسن الحظّ، فهناك خيارات كثيرة أخرى.
وضع CBC
يُعدّ وضع CBC (cipher block chaining، أي تسلسل كتل الشيفرة) وضع تشغيل شائعًا. وقد
يتضمّن هذا الوضع إجراء XOR على كتل النصّ الصريح مع كتلة النصّ المشفَّر السابقة قبل
أن تشفّرها شيفرة الكتل.
وبالطبع، تطرح هذه العملية مشكلة مع أوّل كتلة نصّ صريح: فلا توجد كتلة نصّ مشفَّر
سابقة لإجراء XOR معها. وبدلًا من ذلك، نختار متجه تهيئة (IV): وهو كتلة عشوائية
تحلّ محلّ كتلة النصّ المشفَّر «الأولى». وتظهر متجهات التهيئة
(initialization vector)\s في خوارزميات كثيرة أيضًا. وينبغي أن يكون متجه التهيئة
غير قابل للتنبّؤ، وأن يكون مثاليًّا عشوائيًّا تشفيريًا. ولا يلزم الاحتفاظ بمتجهات
التهيئة سرّية: فغالبًا ما تُضاف مجرّدًا إلى رسائل النصّ المشفَّر وهي نصّ صريح. وقد
يبدو متناقضًا أن يجب ألّا يكون متجه التهيئة قابلًا للتنبّؤ مع ألّا يكون سرّيًا. ومن
المهمّ أن نتذكّر أنّ على المهاجم ألّا يكون قادرًا على التنبّؤ بمتجه تهيئة معيّن
مقدّمًا. وسنوضّح ذلك لاحقًا بهجوم على متجهات تهيئة وضع CBC القابلة للتنبّؤ.
يوضّح المخطّط التالي التشفير في وضع CBC:
وفكّ التشفير هو البناء المعكوس. إذ تكون شيفرات الكتل في وضع فكّ التشفير بدلًا من وضع التشفير:
وفيما أنّ وضع CBC ليس غير آمن بطبيعته (بخلاف وضع ECB)، فإنّ استعماله بعينه في
TLS 1.0 كان غير آمن. وقد أدّى ذلك في النهاية إلى هجوم BEAST، الذي نتناوله بالتفصيل
في قسم SSL/TLS. أمّا الخلاصة فهي أنّ الكتلة المشفَّرة السابقة استُعملت كمتّجه تهيئة
للرسالة التالية، بدلًا من استعمال متجهات تهيئة غير قابلة للتنبّؤ مثل متجهات التهيئة
العشوائية. وللأسف، وجد المهاجمون طريقة لاستغلال هذه الخاصية.
هجمات على وضع CBC مع متجهات تهيئة قابلة للتنبّؤ
لنفترض وجود قاعدة بيانات تخزّن معلومات سرّية عن المستخدمين، مثل السجلّات الطبية أو
رواتب الموظفين أو السجلّات الجنائية. ويحمي الخادم هذه المعلومات بتشفيرها بشيفرة كتل
قويّة في وضع CBC بمفتاح ثابت. ولغرض هذا القسم نفترض أنّ الخادم آمن ولا سبيل إلى
تسريب المفتاح.
تنال موري (Mallory) جميع صفوف قاعدة البيانات. ربّما فعلت ذلك عبر هجوم حقن SQL (SQL injection)، أو ربّما بقليل من الهندسة الاجتماعية (social engineering) [3]. المفترض أن يبقى كلّ شيء آمنًا: فمورّي لا تملك إلّا النصوص المشفَّرة، ولا تملك المفتاح السرّي.
تريد مورّي أن تعرف ما يقوله سجلّ Alice. ولتبسيط الأمر، فلنفترض أنّ هناك كتلة نصّ مشفَّر واحدة فقط. وهذا يعني أنّ نصّ Alice المشفَّر يتكوّن من متجه تهيئة وكتلة نصّ مشفَّر واحدة.
ويبقى بإمكان مورّي أن تحاول استعمال التطبيق كمستخدم عادي، أي أنّ التطبيق سيشفّر بعض البيانات التي تختارها مورّي ويكتبها في قاعدة البيانات. ولنفترض أنّه بسبب خلل في الخادم تستطيع مورّي التنبّؤ بمتجه التهيئة الذي سيُستعمل لنصّها المشفَّر. ربّما يستخدم الخادم المتجه نفسه دائمًا للشخص نفسه، أو يستخدم دائمًا متجه تهيئة أصفار تمامًا، أو…
ويمكن لمورّي أن تبني نصّها الصريح مستعملةً متجه تهيئة Alice الذي تراه IV_A، ومتجه
التهيئة الذي تنبّأت به لنفسها IV_M. وهي تقدّر تخمينًا G لما قد تكون عليه بيانات
Alice. ثمّ تطلب من الخادم أن يشفّر:
P_M = IV_M \xor IV_A \xor G
فيقوم الخادم بأمانة بتشفير تلك الرسالة باستعمال متجه التهيئة التنبّؤي IV_M. وهو
يحسب:
وهذا النصّ المشفَّر، C\ M، هو بالضبط كتلة النصّ المشفَّر التي كانت ستحصل عليها Alice
لو كان نصّها الصريح هو G. لذا، فحسب طبيعة البيانات، تكون مورّي قد عرفت ما إذا كان لدى
Alice سجلّ جنائي أم لا، أو ربّما مرضًا محرجًا من نوع ما، أو مشكلة أخرى كانت Alice
تتوقّع حقًّا من الخادم أن يحفظها سرّية.
الدروس المستفادة: لا تجعل متجهات التهيئة قابلة للتنبّؤ. وأيضًا، لا تصنع أنظمتك التشفيرية بنفسك. ففي نظام آمن، من المرجّح ألّا تكون سجلّات Alice ومورّي مشفَّرة بالمفتاح نفسه.
هجمات على وضع CBC مع المفتاح بوصفه متجه التهيئة
هجمات على وضع CBC مع المفتاح بوصفه متجه التهيئة
تضبط أنظمة CBC كثيرة المفتاح بوصفه متجه التهيئة (initialization vector). ويبدو
هذا فكرةً صالحة: فالطريق إلى ذلك أنّك تحتاج مفتاحًا سرّيًا مشتركًا على أيّ حال.
وهو يؤدّي إلى فائدة أداء جميلة، لأنّ المُرسِل والمستقبِل لا يحتاجان إلى تبادل متجه
التهيئة صراحةً، إذ يعرفان المفتاح (وبالتالي متجه التهيئة) مسبقًا. وإضافةً إلى ذلك،
فالمفتاح غير قابل للتنبّؤ على الإطلاق لأنّه سرّي: فإذا كان قابلًا للتنبّؤ لأمكن
للمهاجم التنبّؤ بالمفتاح مباشرةً، فيكون ذلك مكسبًا له. ومن المناسب تمامًا أنّ تمتلك
شيفرات الكتل كثيرة أحجام كتل مساوية لحجم المفتاح أو أصغر منه، فالمفتاح كبير بما
يكفي.
هذا التكوين غير آمن تمامًا. فإذا أرسلت Alice رسالة إلى Bob، أمكن لمورّي — وهي خصم نشط يستطيع اعتراض الرسالة وتعديلها — أن تنفّذ هجوم نصّ مشفَّر مختار (chosen ciphertext attack) لاستعادة المفتاح.
تحوّل Alice نصّها الصريح P إلى ثلاث كتل P_1 P_2 P_3 وتشفّره في وضع CBC
بالمفتاح السرّي k، وتستعمل k أيضًا بوصفه متجه التهيئة. فتحصل على نصّ مشفَّر من
ثلاث كتل C = C_1 C_2 C_3، ترسله إلى Bob.
قبل أن تصل الرسالة إلى Bob، تعترضها مورّي. وهي تعدّل الرسالة لتصبح
C^{\prime} = C_1 Z C_1، حيث Z كتلة مملوءة ببايتات فارغة (بقيمة صفر).
يفكّ Bob تشفير C^{\prime}، فيحصل على كتل النصّ الصريح الثلاث
P^{\prime}_1, P^{\prime}_2, P^{\prime}_3:
R ما هي إلّا كتلة عشوائية. وقيمتها لا تهمّ.
في إطار افتراض هجوم النصّ المشفَّر المختار، تستعيد مورّي ذلك النصّ بعد فكّ التشفير.
فهي لا تهتمّ إلّا بالكتلة الأولى (:math:P^{\prime}_1 = P_1) والكتلة الثالثة
(P^{\prime}_3 = P_1 \xor IV). وبإجراء XOR بينهما تجد
(P_1 \xor IV) \xor P_1 = IV. لكنّ متجه التهيئة هو المفتاح، لذا فقد استعادت مورّي
المفتاح بنجاح بتعديل رسالة واحدة.
الدرس المستفاد: لا تستعمل المفتاح بوصفه متجه تهيئة. والجزء من المغالطة في المقدّمة هو افتراضها أنّه يمكن استعمال بيانات سرّية لمتجه التهيئة، لأنّه لم يكن مطلوبًا إلّا ألّا يكون قابلًا للتنبّؤ. وليس هذا صحيحًا: فـ«سرّي» مجرّد متطلّب مختلف عن «غير سرّي»، وليس بالضرورة أقوى. وليس من الصواب عمومًا استعمال معلومات سرّية حيث لا تُشترط، وذلك بالضبط لأنّ الخوارزمية قد تتعامل معها على أنها غير سرّية إن لم يكن المفترض أن تكون سرّية، كما هو الحال هنا. وهناك فعلًا أنظمة كثيرة يجوز فيها استعمال سرّ حيث لا يُشترط. وقد تحصل في بعض الحالات على نظام أقوى نتيجةً لذلك، لكنّ النقطة هي أنّ هذا ليس صحيحًا على نحو عامّ، وإنّما يعتمد على ما تفعله.
هجمات قلب البتّات في وضع CBC
يُسمّى أحد الهجمات المثيرة للاهتمام على وضع CBC هجوم قلب البتّات (bit flipping
attack). وباستعمال هجوم قلب بتّات في وضع CBC، يستطيع المهاجمون تعديل النصوص
المشفَّرة في وضع CBC بحيث يكون لها أثر متوقَّع على النصّ الصريح.
قد يبدو هذا تعريفًا غريبًا جدًّا لـ«الهجوم» في أوّل الأمر. فالمهاجم لن يحاول حتى فكّ تشفير أيّ رسالة، بل سيكتفي بقلب بعض البتّات في نصّ صريح. وسنبيّن أنّه يمكن للمهاجم أن يحوّل القدرة على قلب بعض البتّات في النصّ الصريح إلى قدرة على جعل النصّ الصريح يقول ما يشاء بالضبط، ومن ثمّ إنّ ذلك بالطبع قد يؤدّي إلى مشكلات بالغة الخطورة في الأنظمة الحقيقية.
لنفترض لدينا نصًّا مشفَّرًا بوضع CBC. فقد يكون، على سبيل المثال، كعكة (cookie). نأخذ كتلة نصّ مشفَّر بعينها، ونقلب بعض البتّات فيها. فماذا يحدث للنصّ الصريح؟
عنما «نقلب بعض البتّات»، فإنّنا نفعل ذلك بإجراء XOR مع تسلسل من البتّات، سنسمّيه
X. فإذا كان البتّ المقابل في X يساوي 1، فإنّ البتّ يُقلَب؛ وإلّا فسيبقى البتّ
كما هو.
وعنما نحاول فكّ تشفير كتلة النصّ المشفَّر ذات البتّات المقلوبة، سنحصل على ترميز
[4] غير مفهوم. وتذكّر كيف يعمل فكّ التشفير في وضع CBC: فإنّ خرج شيفرة الكتل يُجرى
عليه XOR مع كتلة النصّ المشفَّر السابقة لإنتاج كتلة النصّ الصريح. وبعد أن عُدِّلت
كتلة الدخل المشفَّرة C_i، سيكون خرج شيفرة الكتل كتلة عشوائية لا علاقة لها بشيء،
وبالإحصاء ترميزًا بلا معنى. وبعد إجراء XOR عليها مع كتلة النصّ المشفَّر تلك
السابقة، ستظلّ ترميزًا بلا معنى. ونتيجةً لذلك، تظلّ كتلة النصّ الصريح المنتَجة
ترميزًا بلا معنى. وفي الرسم، هذه الكتلة من النصّ الصريح غير المفهومة هي
P_i^{\prime}.
لكنّ في الكتلة التي تلي تلك، ستُقلَب البتّات التي قلبناها في النصّ المشفَّر في
النصّ الصريح أيضًا! والسبب هو أنّه في فكّ التشفير بوضعية CBC، تُفكّ تشفير كتل النصّ
المشفَّر بواسطة شيفرة الكتل، ثمّ يُجرى على الناتج XOR مع كتلة النصّ المشفَّر
السابقة. لكنّا عدّلنا كتلة النصّ المشفَّر السابقة بإجراء XOR عليها مع X، لذا
فستُجرى عملية XOR على كتلة النصّ الصريح P_{i + 1} مع X أيضًا. ونتيجةً لذلك،
يسيطر المهاجم تحكّمًا تامًّا على كتلة النصّ الصريح تلك P_{i + 1}، إذ يستطيع
ببساطة قلب البتّات التي لا تساوي القيمة التي يريدها لها.
TODO: أضف الرسم السابق، لكنّ ضع مسار تأثير X على P prime {i + 1} بالأحمر أو ما شابه
قد لا يبدو هذا أمرًا بالغ الأهمية في أوّل الأمر. فإذا كنت لا تعرف بايتات النصّ الصريح لتلك الكتلة التالية، فلا سبيل إلى معرفة أيّ البتّات ينبغي قلبها للحصول على النصّ الصريح الذي تريده.
ولتوضيح كيف يمكن للمهاجمين تحويل هذا إلى هجوم عملي، فلنفترض موقعًا يستعمل الكعكات. فعند تسجيلك، يوضع اسم المستخدم الذي اخترته في كعكة. ويشفّر الموقع الكعكة ويرسلها إلى متصفّحك. وفي المرة التالية التي يزور فيها متصفّحك الموقع، سيقدّم له الكعكة المشفَّرة؛ فيفكّ الموقع تشفيرها ويعرف من أنت.
غالبًا ما يستطيع المهاجم التحكّم في جزء على الأقلّ من النصّ الصريح الذي يُشفَّر.
في هذا المثال، اسم المستخدم جزء من النصّ الصريح للكعكة. وبالطبع، يتيح لك الموقع
أن تقدّم أيّ قيمة تريدها لاسم المستخدم عند التسجيل، فيستطيع المهاجم أن يضيف سلسلة
طويلة جدًّا من بايتات Z إلى اسمه. فيقوم الخادم بكلّ سرور بتشفير كعكة كهذه، فيحصل
المهاجم على نصّ مشفَّر يطابق نصًّا صريحًا يحوي عددًا كبيرًا من بايتات Z هذه. ومن
المرجّح أن يكون النصّ الصريح الذي سيُعدَّل جزءًا من ذلك التسلسل من بايتات Z.
قد يمتلك المهاجم بعض البايتات الهدف التي يودّ رؤيتها في النصّ الصريح بعد فكّ التشفير،
مثل ;admin=1;. ولأجل معرفة أيّ البايتات ينبغي أن يقلبها (أي قيمة X في الرسم)،
يكفي أن يُجري المهاجم XOR على بايتات الحشو (~ZZZ~…) مع تلك القيمة الهدف. ولأنّ
عمليتي XOR بالقيمة نفسها تُلغي كلّ منهما الأخرى، فإنّ قيمتَي الحشو (~ZZZ~…) ستُلغيان،
فيستطيع المهاجم توقّع ظهور ;admin=1; في كتلة النصّ الصريح التالية:
وهذا الهجوم مثال آخر على مبدأ تشفيري مهمّ: التشفير ليس مصادقة! فكبساطة تشفير رسالة لا تكفي عمليًّا أبدًا. وقد تمنع المهاجم من قراءتها، لكنّ ذلك غالبًا لا يكون ضروريًّا حتى يتمكّن المهاجم من تعديلها ليقول ما يريد أن يقوله. ويمكن حلّ هذه المشكلة بعينها عبر المصادقة الآمنة على الرسالة أيضًا. وسنرى في وقت لاحق من الكتاب كيف نفعل ذلك؛ أمّا الآن فمجرد تذكّر أنّنا سنحتاج إلى المصادقة كي ننتج أنظمة تشفير آمنة.
الحشو
حتى الآن، افترضنا بكلّ بساطة أنّ جميع الرسائل تصادف أن تناسب نظام شيفرات الكتل تمامًا، سواء كان CBC أو ECB. وهذا يعني أنّ جميع الرسائل تصادف أن تكون مضاعفات لحجم الكتلة، وهو 16 بايتًا في شيفرة كتل معتادة مثل AES. وبالطبع، قد تكون الرسائل الحقيقية بأيّ طول. فنحتاج إلى بعض الآلية لجعلها تناسب. وتُسمَّى هذه العملية حشوًا (padding).
الحشو بالأصفار (أو بايت حشو آخر)
الحشو بالأصفار (أو بايت حشو آخر)
إحدى طرق الحشو هي إلحاق قيمة بايت بعينها فقط إلى أن يبلغ النصّ الصريح الطول المناسب. ولإلغاء الحشو، ما عليك سوى إزالة تلك البايتات. لكن في هذا المخطط خللًا واضحًا: إذ لا يمكنك إرسال رسائل تنتهي بتلك القيمة البايتية بعينها، وإلّا فلن تستطيع التمييز بين الحشو والنصّ الفعليّ.
حشو PKCS#5/PKCS#7
والمخطّط الأفضل، وأكثره شيوعًا بكثير، هو حشو PKCS#5/PKCS#7.
حشو PKCS#5 وPKCS#7 وحشو CMS اللاحق هي جميعها الفكرة نفسها إلى حدٍّ كبير [5]. خذ
عدد البايتات التي عليك حشوها، واحشوها بذلك العدد من المرّات للبايت ذي تلك القيمة.
فمثلًا، إذا كان حجم الكتلة 8 بايتات، وكانت الكتلة الأخيرة تحوي البايتات الثلاثة
12 34 45، فإنّ الكتلة تصير 12 34 45 05 05 05 05 05 بعد الحشو.
ولو وقع النصّ الصريح من مضاعفات حجم الكتلة بالضبط، لاستُعملت كتلة كاملة من الحشو. وإلّا فإنّ المستقبِل سينظر إلى البايت الأخير من النصّ الصريح، ويعتبره طولًا للحشو، وسيستنتج على الأرجح أنّ الرسالة لم تُحشَ على النحو الصحيح.
وهذا المخطّط موصوف في cms:padding.
هجمات حشو CBC
يمكننا تنقيح هجمات قلب البتّات في وضع CBC حتى نخدع المستقبِل على فكّ تشفير رسائل اختيارية!
وكما ناقشنا توًّا، يشترط وضع CBC حشو الرسالة حتى تصير مضاعفات لحجم الكتلة. فإذا
كان الحشو خاطئًا، فإنّ المستقبِل يرفض الرسالة عادةً ويقول إنّ الحشو غير صالح. ويمكننا
أن نستعمل تلك المعلومة البسيطة عن حشو النصّ الصريح لنُفكّ تشفير الرسالة كاملة بشكل
تكراريّ.
وهذا ما سيفعله المهاجم، كتلة نصّ مشفَّر في كلّ مرّة، بمحاولة الحصول على حشو صالح يساوي قيمة كتلة نصّ صريح كاملة. وسنرى أنّ هذا يكشف له فكّ تشفير كتلة النصّ المشفَّر التي يستهدفها تحت شيفرة الكتل. وسنرى أيضًا أنّه يمكن فعل ذلك بكفاءة وبشكل تكراريّ، مجردًا من ذلك التسرّب القليل من المعلومات عن صحّة الحشو من عدمها.
قد يكون من المفيد أن تضع في ذهنك أنّ هجوم حشو CBC لا يهاجم الحشو الخاص برسالة معطاة؛ بل إنّ المهاجم يبني حشوات ليُفكّ تشفير رسالة.
ولتنفيذ هذا الهجوم، لا يحتاج المهاجم إلّا أمرين:
#. نصّ مشفَّر هدف يفكّ تشفيره #. آلة حشو (padding oracle): وهي دالة تأخذ النصوص المشفَّرة وتخبر المهاجم ما إذا كان الحشو صحيحًا
وكما في آلة التشفير (encryption oracle) الخاصة بوضع ECB، قد يبدو افتراض توفّر
آلة حشو افتراضًا غير واقعيّ إلى حدٍّ كبير. لكنّ الأثر الهائل لهذا الهجوم يثبت
خلاف ذلك. فمدّة طويلة لم تحاول معظم الأنظمة أصلًا إخفاء ما إذا كان الحشو صالحًا أم
لا. وقد ظلّ هذا الهجوم خطيرًا مدّة طويلة بعد اكتشافه أوّل مرّة، لأنّه اتّضح أنّه في
أنظمة كثيرة يصعب على نحوٍ شديد إخفاء صلاحية الحشو فعلًا. وسنتناول هذه المشكلة بمزيد
من التفصيل في هذا الفصل وفي الفصول اللاحقة.
في هذا الفصل، سنفترض استعمال حشو PKCS#5/PKCS#7، إذ إنّ ذلك هو الخيار الأكثر شيوعًا. والهجوم عامّ بما يكفي ليعمل مع أنواع أخرى من الحشو مع تعديلات طفيفة.
فكّ تشفير البايت الأوّل
يملأ المهاجم كتلة ببايتات اعتباطية R = r_1, r_2\ldots r_b. كما يختار كتلة هدف
C_i من النصّ المشفَّر يودّ فكّ تشفيرها. ثمّ يسأل المهاجم آلة الحشو هل للنصّ
الصريح المقابل لـR \| C_i حشو صالح. وبالإحصاء، على الأرجح ألّا يكون لهذا النصّ
الصريح العشوائي حشو صالح: فالاحتمالات في حدود نصف بالمئة. وإذا اتّفق بالصدفة أن
تكون الرسالة تملك حشوًا صالحًا أصلًا، فيمكن للمهاجم ببساطة تخطّي الخطوة التالية.
ثمّ يحاول المهاجم تعديل الرسالة بحيث تملك حشوًا صالحًا. ويمكنه فعل ذلك بتعديل
البايت الأخير من النصّ الصريح تعديلًا غير مباشر: فسينتهي ذلك البايت إلى أن يساوي
01، وهو حشو صالح دائمًا. ولتعديل البايت الأخير من كتلة النصّ الصريح، يعدّل
المهاجم البايت الأخير من كتلة النصّ المشفَّر السابقة. وهذا يعمل تمامًا كما كان
يعمل في هجمات قلب البتّات في وضع CBC. تلك الكتلة المشفَّرة السابقة هي الكتلة R،
فالبايت الذي يجري تعديله هو البايت الأخير من R، أي r_b.
يجرّب المهاجم جميع القيم الممكنة لذلك البايت الأخير. وهناك طرق عديدة للقيام بذلك:
الجمع النمطي، أو إجراء XOR معه بقيم من 0 إلى 255 جميعها، أو حتى الاختيار العشوائي؛
والشيء الوحيد الذي يهمّ هو أن يجرّب المهاجمها جميعها. وفي نهاية المطاف، ستُبلّغ آلة
الحشو بأنّ هناك كتلة نصّ مشفَّر R يكون فيها النصّ الصريح المقابل لـR \| C_i ذا
حشو صالح.
اكتشاف طول الحشو
لقد أخبرت آلة الحشو توًّا المهاجم بأنّ قيمة R التي اخترناها تُنتج نصًّا صريحًا
لـR \| C_i ذا حشو صالح. وبما أننا نتعامل مع حشو PKCS#5، فهذا يعني أنّ كتلة النصّ
الصريح P_i تنتهي بأحد تسلسلات البايتات التالية:
0102 0203 03 03- …
الخيار الأوّل (01) أرجح بكثير من غيره، لأنّه لا يشترط إلّا أن يملك بايت واحد قيمة
معيّنة. فالمهاجم يعدّل ذلك البايت ليأخذ كلّ القيم الممكنة، لذا من المرجّح جدًّا
أن يصادف 01. أمّا خيارات الحشو الصالحة الأخرى فتتطلّب، زيادةً على اشتراط أن يملك
ذلك البايت قيمة معيّنة، بايتًا واحدًا أو أكثر. ولكي يضمن المهاجم رسالة ذات حشو
01 صالح، ما عليه إلّا تجريب كلّ بايت ممكن. أما لينتهي به المطاف إلى رسالة ذات حشو
02 02 صالح، فعليه أن يجرّب كلّ بايت ممكن وأن يصادف تركيبة من C وR تجعل
النصّ الصريح يحوي 02 في ذلك الموضع ما قبل الأخير. (بعبارة أخرى: البايت ما قبل
الأخير من فكّ تشفير كتلة النصّ المشفَّر، بعد إجراء XOR عليه مع البايت ما قبل الأخير
من R، يساوي 02.)
ولنُفكّ تشفير الرسالة بنجاح، ما زلنا بحاجة إلى معرفة أيّ تلك الخيارات يمثّل قيمة
الحشو الفعلية. ولتحقيق ذلك، نحاول اكتشاف طول الحشو بتعديل البايتات بدءًا من الجهة
اليسرى من P_i إلى أن يصير الحشو غير صالح من جديد. وكما في كلّ شيء آخر في هذا
الهجوم، فإنّنا يعدّلون تلك البايتات في P_i بتعديل البايتات المكافئة لها في كتلتنا
المختارة R. وفي اللحظة التي ينكسر فيها الحشو، تعرف أنّ آخر بايت عدّلته كان جزءًا
من الحشو الصالح، وهذا يخبرك بعدد بايتات الحشو. وبما أنّنا نستعمل حشو PKCS#5، فإنّه
يخبرك أيضًا بقيمتها.
لنوضّح ذلك بمثال. فلنفترض أنّنا وجدنا بنجاح كتلة R بحيث يكون للنصّ الصريح
المقابل لـR \| C_i حشو صالح. ولنفترض أنّ ذلك الحشو هو 03 03 03. وطبيعيًّا،
لن يعرف المهاجم ذلك؛ فغرض هذه Procedure هو اكتشاف ماهيّة ذلك الحشو. ولنفترض أنّ
حجم الكتلة 8 بايتات. إذًا، نحن (وليس المهاجم) نعرف أنّ P_i هي حاليًّا:
في تلك المعادلة، p_0 \ldots هي بعض بايتات النصّ الصريح. ولا يهمّ قيمتها الفعلية:
فالشأن الوحيد الذي يهمّ هو أنّها ليست جزءًا من الحشو. وعنما نعدّل البايت الأوّل من
R، فإنّنا نُحدث تغييرًا في البايت الأوّل من P_i، بحيث يصبح p_0 بايتًا آخر
p^{\prime}_0:
وكما ترى، فإنّ هذا لا يؤثّر في صحّة الحشو. كما أنّه لا يؤثّر في p_1 أو p_2 أو
p_3 أو p_4. لكنّا عنما نواصل تعديل البايتات التالية، سنصطدم في النهاية ببايت
هو جزء من الحشو. فمثلًا، ولنفترض أنّنا نحوّل ذلك 03 الأوّل إلى 02 بتعديل R.
فتصير P_i على هذا النحو:
وبما أنّ 02 03 03 ليس حشو PKCS#5 صالحًا، فإنّ الخادم سيرفض الرسالة. وفي تلك
اللحظة، نعرف أنّه ما إن تعدّل ستّة بايتات حتى ينكسر الحشو. وهذا يعني أنّ البايت
السادس هو البايت الأوّل من الحشو. وبما أنّ طول الكتلة 8 بايتات، فنحن نعرف أنّ الحشو
يتكوّن من البايتات السادس والسابع والثامن. أي إنّ الحشو بطول ثلاثة بايتات، وأنّه في
PKCS#5 يساوي 03 03 03.
والمهاجم الذكيّ الذي يحاول تقليل عدد استعلامات الآلة يمكنه أن يستفيد من الحقيقة
القائلة بأنّ الحشو الصالح الأطول يزداد ندرةً تدريجيًا. ويستطيع ذلك بأن يبدأ من
البايت ما قبل الأخير بدلًا من بداية الكتلة. وميزة هذه الطريقة أنّ الحشوات
القصيرة (وهي الأكثر شيوعًا) تُكتشَف أسرع. فمثلًا، إذا كان الحشو هو 0x01 وبدأ
المهاجم بتعديل البايت ما قبل الأخير، فلا يحتاج إلّا استعلامًا واحدًا ليعرف ما هو
الحشو. فإذا تغيّر البايت ما قبل الأخير إلى أيّ قيمة أخرى وما زال الحشو صالحًا،
فيجب أن يكون الحشو هو 0x01. وإذا لم يكن الحشو صالحًا، فيجب ألّا يقلّ الحشو عن
0x02 0x02. عاد المهاجم إذًا إلى الكتلة الأصلية وبدأ يعدّل البايت الثالث من
الخلف. فإذا اجتاز ذلك، فالحشو كان بالفعل 0x02 0x02، وإلّا فيجب ألّا يقلّ الحشو
عن 0x03 0x03 0x03. وتتكرّر العملية حتى يجد الطول الصحيح. وهذه التقنية أعسر
قليلًا في التطبيق؛ إذ لا يمكنك ببساطة مواصلة تعديل الكتلة نفسها (إن كانت
قابلة للتغيير)، وأنت تنتظر أن تفشل الآلة بدلًا أن تنجح، وهذا قد يكون محيّرًا. لكنّها
مكافئة للتقنية الموصوفة أعلاه، فيما أنّها أسرع ثمنًا بعض التعقيد.
في القسم التالي، سنفترض أنّ الحشو كان 01 فحسب، إذ إنّ ذلك هو الحالة الأكثر شيوعًا.
فالهجوم لا يتغيّر فعليًّا حسب طول الحشو. فإذا خمّنت بايتات أكثر من الحشو على نحو
صحيح، فإنّ ذلك يعني مجرّدًا أنّ عدد البايتات المتبقّية التي عليك تخمينها يدويًّا أقلّ.
(وستصبح واضحةً تلك الحقيقة بمجرد أن تفهم بقية الهجوم.)
فكّ تشفير بايت واحد
في هذه المرحلة، يكون المهاجم قد نجح فعلًا في فكّ تشفير البايت الأخير من كتلة النصّ
المشفَّر الهدف! وفي الحقيقة، لقد فككنا تشفير عدد البايتات الذي يساوي طول الحشو
الصالح؛ ونحن نفترض هنا أسوأ حالة، وهي وجود بايت واحد فقط. كيف ذلك؟ يعرف المهاجم
أنّ البايت الأخير من كتلة النصّ المشفَّر C_i بعد فكّ التشفير (وسنسمّيه ذلك البايت
D(C_i)[b])، بعد إجراء XOR عليه مع القيمة r_b التي عُثر عليها تكراريًّا، يساوي
01:
وبنقل عملية XOR إلى الجهة الأخرى، يحصل المهاجم على:
وهكذا يكون المهاجم قد خدع المستقبِل في إفشاء قيمة البايت الأخير من فكّ تشفير كتلة
C_i بواسطة شيفرة الكتل.
فكّ تشفير البايتات التالية
بعد ذلك، يخدع المهاجم المستقبِل في فكّ تشفير البايت التالي. وتذكّر المعادلة السابقة،
التي استنتجنا فيها أنّ البايت الأخير من النصّ الصريح كان 01:
والآن نودّ أن نجعل ذلك البايت يساوي 02، لإنتاج حشو شبه صالح: فالبايت الأخير
سيكون صحيحًا بالنسبة إلى حشو PKCS#5 بطول بايتين (02 02)، لكنّ ذلك البايت ما قبل
الأخير على الأرجح ليس 02 بعد. ولتحقيق ذلك، نُجري XOR مع 01 لإلغاء 01 الموجودة
بالفعل (لأنّ عمليتي XOR بالقيمة نفسها تُلغي كلّ منهما الأخرى)، ثمّ نُجري XOR مع
02 للحصول على 02:
إذن، لإنتاج قيمة 02 في الموضع الأخير من النصّ الصريح بعد فكّ التشفير، يستبدل
المهاجم r_b بـ:
وهذا يحقّق الهدف من الحشو شبه الصالح. ثمّ يجرّب جميع القيم الممكنة للبايت ما قبل
الأخير (الفهرس b - 1). وفي نهاية المطاف، سيجعل أحدُها الرسالة تملك حشوًا صالحًا.
وبما أنّنا عدّلنا الكتلة العشوائية بحيث يصير البايت الأخير من النصّ الصريح 02،
فإنّ البايت الوحيد في الموضع ما قبل الأخير الذي يمكنه أن يُنتج حشوًا صالحًا هو 02
أيضًا. وباستعمال الرياضيات نفسها أعلاه، يكون المهاجم قد استعاد البايت ما قبل الأخير.
ثمّ لا يبقى إلّا تكرار العمل. إذ تُعدَّل البايتان الأخيرتان لإنتاج حشو شبه صالح
03 03، ثمّ يُعدَّل البايت الثالث من اليمين حتى يصير الحشو صالحًا، وهكذا. وتكرار
هذا على جميع بايتات الكتلة يعني أنّ المهاجم يستطيع فكّ تشفير الكتلة بأكملها؛ وتكراره
على كتل مختلفة يعني أنّه يستطيع قراءة الرسالة بأكملها.
لقد تبيّن أنّ هذا الهجوم دقيق جدًّا ويصعب إصلاحه. أوّلًا، ينبغي مصادقة الرسائل إضافةً إلى تشفيرها. وذلك كان سيجعل الرسائل المعدَّلة تُرفض. لكنّ أنظمة كثيرة تفكّ التشفير (وتزيل الحشو) قبل أن تصادق على الرسالة؛ لذا فقد تسرّبت بالفعل معلومة صحّة الحشو من عدمها. وسنتناول في وقت لاحق من الكتاب طرائق آمنة لمصادقة الرسائل.
قد تفكّر في التخلّص من رسالة «الحشو غير صالح» وإسقاطها تمامًا؛ أي إعلان أنّ الرسالة غير صالحة من دون تحديد سبب بطلانها. لكنّ ذلك لا يتبيّن ليكون حلًّا جزئيًّا إلّا في الأنظمة التي تفكّ التشفير قبل أن تصادق. فتلك الأنظمة ترفض عادةً الرسائل ذات الحشو غير الصالح أبطأ قليلًا من الرسائل ذات الحشو الصالح. فبعد كلّ هذا، فهي لم تكن بحاجة إلى إجراء خطوة المصادقة: فإذا كان الحشو غير صالح، لا يمكن أن تكون الرسالة صالحة إطلاقًا. ويُسمّى الهجوم الذي يسرّب معلومات سرّية عبر فروق التوقيت هجوم توقيت (timing attack)، وهو حالة خاصة من هجوم قناة جانبية (side-channel attack): هجمات على التنفيذ العملي لنظام تشفير بدلًا من تمثيله المجرّد «الكامل». وسنتحدّث عن هذه الأنواع من الهجمات أكثر لاحقًا في الكتاب.
وكان هذا التعارض مستغلًّا على نطاق واسع أيضًا. فبقياس المدة التي يستغرقها المستقبِل لرفض الرسالة، يستطيع المهاجم أن يعرف ما إذا كان المستقبِل قد أجرى خطوة المصادقة. وهذا يخبره ما إذا كان الحشو صحيحًا أم لا، ويوفّر له آلة الحشو التي تُكمل الهجوم.
والدرس الرئيس المستفاد هنا هو أيضًا عدم تصميم أنظمتك التشفيرية بنفسك. والطريقة الرئيسة لتفادي هذه المشكلة بعينها هي إجراء المصادقة في زمن ثابت (constant time)، ومصادقة النصّ المشفَّر قبل فكّ تشفيره. وسنتحدّث عن هذا أكثر في فصل لاحق عن مصادقة الرسائل.
شيفرات التيار الأصلية
إضافةً إلى شيفرات الكتل المستعملة في وضع تشغيل (mode of operation) معيّن، هناك
أيضًا خوارزميات «أصلية» (native) لـشيفرة التيار (stream cipher) مصمَّمة من الأساس
لأن تكون شيفرة تيار.
أكثر أنواع شيفرة التيار شيوعًا هو ما يُسمّى شيفرة تيار متزامنة (synchronous). فهذه الخوارزميات تنتج تدفّقًا طويلًا من البتّات شبه العشوائية انطلاقًا من مفتاح متماثل سرّي. ثمّ يُجرى XOR على هذا التدفّق — الذي يُسمّى تدفّق المفاتيح (keystream) — مع النصّ الصريح لإنتاج النصّ المشفَّر. وفكّ التشفير هو العملية نفسها تمامًا التي تُكرَّر: فتدفّق المفاتيح يُنتَج من المفتاح، ثمّ يُجرى عليه XOR مع النصّ المشفَّر لإنتاج النصّ الصريح.
يمكنك أن ترى كيف يبدو هذا البناء مشابهًا إلى حدٍّ كبير لوسادة المرّة الواحدة، إلّا أنّ وسادة المرّة الواحدة العشوائية حقًّا قد استُبدلت بشيفرة تيار شبه عشوائية.
وهناك أيضًا شيفرات تيار غير متزامنة (asynchronous) أو ذاتية تزامن (self-synchronizing)، تُستخدم فيها البتّات المشفَّرة المنتَجة سابقًا لإنتاج بتّ تدفّق المفاتيح الحالي. ولهذا نتيجة مثيرة: إذ يستطيع المستقبِل في نهاية المطاف أن يستعيد الحال إذا سقطت بعض البتّات المشفَّرة. ولم يعد هذا يُعدّ خاصية مرغوبة في الأنظمة التشفيرية الحديثة، والتي تفضّل بدلًا من ذلك إرسال رسائل كاملة ومصادق عليها. ونتيجةً لذلك، فإنّ هذه الشيفرات نادرة جدًّا، ولا نتحدّث عنها صراحةً في هذا الكتاب. فكلّما قال أحدهم «شيفرة تيار»، فمن الآمن أن نفترض أنّه يقصد النوع المتزامن.
تاريخيًّا، كان لدى شيفرات التيار الأصلية مشكلاتها. فمثلًا، مسابقة NESSIE الدولية لبناءات تشفيرية جديدة لم تسفر عن أيّ شيفرات تيار جديدة، لأنّ جميع المشاركين كُسروا قبل انتهاء المسابقة. أمّا RC4، إحدى أكثر شيفرات التيار الأصلية شيوعًا، فقد كانت لديها مشاكل معروفة خطيرة لسنوات. وبالمقارنة، تبدو بعض التركيبات المبنية على شيفرات الكتل خالية من الثغرات.
ولحسن الحظّ، فقد طوّرت مؤخّرًا عدة خوارزميات تشفير جديدة تمنحنا أملًا جديدًا في الحصول على شيفرات تيار عملية وآمنة وسريعة الأداء.
RC4
من بعيد أكثر شيفرة تيار أصلية استعمالًا شائعةً على أجهزة سطح المكتب والهواتف المحمولة هي RC4.
وتُسمّى RC4 أحيانًا أيضًا ARCFOUR أو ARC4، وهما اختصار لعبارة RC4 «المزعومة» (alleged). ورغم أنّ شيفرتها المصدرية قد سُرّبت وأنّ تنفيذها معروف الآن على نحو جيّد، فإنّ RSA Security (الشركة التي كتبت RC4 ولا تزال تحتجز علامة RC4 التجارية) لم تعترف قطّ بأنّها الخوارزمية الحقيقية.
وقد سرعت شعبيّتها بسرعة لأنّها بسيطة جدًّا وسريعة جدًّا. فهي ليست سهلة التنفيذ
فحسب، بل سهلة التطبيق أيضًا. وبكونها شيفرة تيار متزامنة، فقلّ ما يمكن أن يسوء؛
أمّا مع شيفرة كتلة فينبغي أن تقلق على أمور مثل أوضاع التشغيل والحشو. وبقياس زمنها
بنحو 13.9 دورة لكلّ بايت، فإنّها قابلة للمقارنة مع AES-128 في وضعي CTR
(12.6 دورة لكلّ بايت) وCBC (16.0 دورة لكلّ بايت). وقد ظهرت AES بضع سنوات بعد RC4؛
فعند تصميم RC4 كان تحالف آنذاك هو 3DES، وهي بطيئة إلى حدّ مؤلم بالمقارنة
(134.5 دورة لكلّ بايت في CTR mode). cryptopp:bench
نظرة معمَّقة على RC4
متقدّم
على الجهة المقابلة، فإنّ RC4 بسيطة إلى حدٍّ مذهل، وقد يستحقّ هذا القسم قراءة سريعة.
وللأسف، فإنّ RC4 مكسورة إلى حدٍّ كبير. ولمعرفة مقدار انهيارها على نحو أفضل، سننظر
في كيفية عمل RC4. ويتطلّب هذا الشرط فهم الجمع النمطي (modular addition)؛ فإن لم تكن
متمكّنًا منه، فقد ترغب في مراجعة :ref:الملحق عن الجمع النمطي <Modular addition>.
يدور كلّ شيء في RC4 حول مصفوفة حالة (state array) وفهرسين داخل تلك المصفوفة. وتتألّف
المصفوفة من 256 بايتًا تشكّل تبديلًا (permutation): أي إنّ جميع قيم الفهارس
الممكنة ترد كلّها مرّة واحدة بالضبط كقيم في المصفوفة. وهذا يعني أنّها تُسقِط كلّ قيمة
بايت ممكنة على كلّ قيمة بايت ممكنة: عادةً على قيمة مختلفة، لكنّها أحيانًا على القيمة
نفسها. ونعرف أنّها تبديل لأنّ S يبدأ بوصفه تبديلًا، وأنّ جميع العمليات التي تعدّل
S تبدّل القيم دائمًا، وهو ما يُبقيه تبديلًا بطبيعة الحال.
تتألف RC4 من مكوّنين رئيسيين يعملان على فهرسين i, j ومصفوفة الحالة S:
#. خوارزمية جدولة المفاتيح (key scheduling algorithm)، التي تنتج مصفوفة حالة
أوّلية S لمفتاح معيّن.
#. المولّد شبه العشوائي (pseudorandom generator)، الذي ينتج بايتات تدفّق المفاتيح
الفعلية من مصفوفة الحالة S التي أنتجتها خوارزمية جدولة المفاتيح. والمولّد
شبه العشوائي نفسه يعدّل مصفوفة الحالة وهو ينتج بايتات تدفّق المفاتيح.
خوارزمية جدولة المفاتيح
تبدأ خوارزمية جدولة المفاتيح بـالتبديل الهويّ (identity permutation). أي إنّ كلّ بايت يُسقَط على نفسه.
ثمّ يُمزج المفتاح في الحالة. ويتم ذلك بجعل الفهرس i يتكرّر على كلّ عنصر
من عناصر الحالة. أمّا الفهرس j فيُعثر عليه بجمع القيمة الحالية لـj (بدءًا من 0)
مع البايت التالي من المفتاح ومع عنصر الحالة الحالي:
وبعد العثور على j، تُبدَّل S[i] وS[j]:
وتتكرّر هذه العملية على جميع عناصر S. فإذا نفدت بايتات المفتاح، فإنّك تعيد
البدء من أوّل المفتاح. وهذا يفسّر لماذا تقبل RC4 مفاتيح يتراوح طولها بين 1 و256
بايتًا. وعادةً تُستعمل مفاتيح بطول 128 بتًّا (16 بايتًا)، ما يعني أنّ كلّ بايت في
المفتاح يُستعمل 16 مرّة.
أو، في Python:
from itertools import cycle
def key_schedule(key):
s = range(256)
key_bytes = cycle(ord(x) for x in key)
j = 0
for i in range(256):
j = (j + s[i] + next(key_bytes)) % 256
s[i], s[j] = s[j], s[i]
return s
المولّد شبه العشوائي
المولّد شبه العشوائي مسؤول عن إنتاج بايتات شبه عشوائية من الحالة S. وتُشكّل هذه
البايتات تدفّق المفاتيح، ويُجرى عليها XOR مع النصّ الصريح لإنتاج النصّ المشفَّر.
ولكلّ فهرس i، يحسب j = j + S[i] (مع بداية j من 0). ثمّ تُبدَّل S[i] وS[j]:
ولإنتاج بايت الخرج، تُجمع S[i] وS[j] معًا. ويُستعمل مجموعهما فهرسًا في S؛
فتكون القيمة عند S[S[i] + S[j]] هي بايت تدفّق المفاتيح K_i:
ويمكننا التعبير عن ذلك في Python:
def pseudorandom_generator(s):
j = 0
for i in cycle(range(256)):
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
k = (s[i] + s[j]) % 256
yield s[k]
الهجمات
متقدّم
قسم الهجمات على RC4 أعقد بكثير من RC4 نفسها، لذا فقد ترغب في تخطّيه حتى وإن قرأت إلى هذا الحدّ.
وهناك هجمات كثيرة على الأنظمة التشفيرية المستعملة لـ RC4 لا تكون فيها RC4 نفسها هي المشكلة، بل إنّ سببها أشياء مثل إعادة استعمال المفتاح أو الإخفاق في مصادقة الرسالة. ولن نتحدّث عن هذه في هذا القسم. فحاليًا لا نتحدّث إلّا عن المشكلات الخاصة بخوارزمية RC4 نفسها.
وكما يمكن تذكّره حدسيًّا، يتّضح كيف تنتج شيفرة تيار مثالية تدفّقًا من البتّات العشوائية. فبعد كلّ هذا، لو كان هذا ما تفعله، لكنّا سنقع في وضع مشابه جدًّا لوسادة المرّة الواحدة.
نظام وسادة المرّة الواحدة.
نظام شيفرة تيار متزامنة. لاحظ التشابه مع نظام وسادة المرّة الواحدة. والفرق
الحاسم هو أنّ وسادة المرّة الواحدة k_i عشوائية حقًّا، في حين أنّ تدفّق المفاتيح
K_i شبه عشوائيّ فحسب.
تكون شيفرة التيار مثالية إذا كانت أفضل طريقة لدينا لمهاجمتها هي تجريب جميع المفاتيح، وهي عمليّة تُسمّى تفريغ المفتاح بالقوة الغاشمة. فإذا كانت هناك طريقة أسهل، مثلًا عبر انحياز (bias) في بايتات الخرج، فإنّ ذلك خلل في شيفرة التيار.
وعلى مدى تاريخ RC4، وجد الناس انحيازات كثيرة من هذا النوع. وفي منتصف التسعينيات، لاحظ Andrew Roos خللين من هذا النوع:
- البايتات الثلاثة الأولى من المفتاح مرتبطة بالبايت الأوّل من تدفّق المفاتيح.
- البايتات الأولى القليلة من الحالة مرتبطة بالمفتاح بعلاقة بسيطة (خطّية).
بالنسبة إلى شيفرة تيار مثالية، لا ينبغي أن يخبرني البايت الأوّل من تدفّق المفاتيح شيئًا عن المفتاح. أمّا في RC4، فيخبرني بمعلومات عن البايتات الثلاثة الأولى من المفتاح. ويبدو الثاني أقلّ خطورة: فبعد كلّ هذا، لا يُفترض بالمهاجم أن يعرف حالة الشيفرة.
وكما هي الحال دائمًا، لا تسوء الهجمات أبدًا، بل تتحسّن فقط.
أظهر Adi Shamir وItsik Mantin أنّ البايت الثاني الذي تنتجه الشيفرة احتمال أن
يساوي صفرًا بمرّتين أكبر ممّا ينبغي. وأظهر باحثون آخرون انحيازات مماثلة في
البايتات الأولى القليلة من تدفّق المفاتيح. وأطلق ذلك مزيدًا من البحث من قِبل
Mantin وShamir وFluhrer، أظهروا انحيازات كبيرة في البايتات الأولى من تدفّق
المفاتيح. fms:rc4 وأظهروا أيضًا أنّ معرفة أجزاء صغيرة حتى من المفتاح تتيح
للمهاجمين إجراء تنبّؤات قوية حول حالة الشيفرة ومخرجاتها. وبخلاف RC4، توفّر معظم
شيفرات التيار الحديثة وسيلة لدمج مفتاح طويل الأمد مع رقم فريد (nonce، أي رقم
يُستعمل مرّة واحدة)، لإنتاج تدفّقات مفاتيح مختلفة متعدّدة من المفتاح طويل الأمد
نفسه. أمّا RC4 وحدها فلا تفعل ذلك. وكان أشيع منهج هو أيضًا أبسطه:
وهو أن ندمج [6] المفتاح طويل الأمد k مع الرقم الفريد n: k \| n، مع
الاستفادة من مرونة RC4 في متطلّبات طول المفتاح. وفي هذا السياق، يعني الدمج أنّ بتّات n تُلحق ببتّات k. وقد أدّى هذا المخطّط إلى
تمكين المهاجمين من استعادة أجزاء من المفتاح المدموج، وفي نهاية المطاف من استعادة
المفتاح طويل الأمد ببطء من عدد كبير من الرسائل (نحو 2^{24} إلى 2^{26}، أي
عشرات الملايين من الرسائل).
وقد تعرّض WEP، وهو معيار لحماية الشبكات اللاسلكية كان شائعًا في ذلك الوقت، لتأثير
هذا الهجوم بشدّة، لأنّه كان يستعمل مخطّط دمج الرقم الفريد البسيط هذا. أمّا
المخطّط الذي يُدمج فيه المفتاح طويل الأمد والرقم الفريد دمجًا آمنًا (مثلًا باستعمال
دالة اشتقاق مفاتيح أو دالة تجزئة تشفيرية) لما كان ليعاني هذا الضعف. ولذلك لم
تتأثّر معايير أخرى كثيرة منها TLS.
ومرةً أخرى، لا تسوء الهجمات بل تتحسّن فقط. وقد أظهر Andreas Klein ارتباطًا أوسع
بين المفتاح وتدفّق المفاتيح. klein:rc4 فبدلًا من عشرات الملايين من الرسائل مع
هجمات Fluhrer وMantin وShamir، لم يعد المهاجمون بحاجة إلّا إلى بضع عشرات من الآلاف
من الرسائل لجعل الهجوم عمليًّا. وقد طُبِّق ذلك على WEP بنجاح كبير.
وفي سنة 2013، أنتج فريق من الباحثين في Royal Holloway في لندن تركيبة لهجومين عمليّين
مستقلّين rhul:rc4. وقد أثبتت هذه الهجمات أنّها قاضية على RC4 إلى حدٍّ بعيد: فبينما
كانت نقاط ضعف RC4 معروفة مدّة طويلة، فإنّها جعلت الجميع في نهاية المطاف يدركون
بوضوح أنّه لا ينبغي حقًّا استعمالها بعد اليوم.
يعتمد الهجوم الأوّل على انحيازات البايت المفرد في البايتات الأولى الـ256 من تدفّق المفاتيح. فبإجراء تحليل إحصائي على تدفّقات المفاتيح التي تنتجها عدّة كبيرة من المفاتيح، تمكّنوا من تحليل الانحيازات المعروفة أصلًا في بايتات تدفّق المفاتيح الأولى في RC4 بتفصيل أكبر بكثير.
TODO: أضف رسمًا توضيحيًّا: http://www.isg.rhul.ac.uk/tls/RC4_keystream_dist_2_45.txt
ويعتمد الهجوم الثاني على انحيازات البايت المزدوج في أيّ موضع من تدفّق المفاتيح. وقد تبيّن أنّ بايتات تدفّق المفاتيح المتجاورة لها علاقة قابلة للاستغلال، في حين أنّنا نتوقّع في شيفرة تيار مثالية أن تكون مستقلّة تمامًا.
==================== ========================================= =============================
زوج البايتات موضع البايت (mod 256) i الاحتمال
==================== ========================================= =============================
(0, 0) i = 1 2^{-16} (1 + 2^{-9})
(0, 0) i \not \in \{{1, 255}\} 2^{-16} (1 + 2^{-8})
(0, 1) i \not \in \{{0, 1}\} 2^{-16} (1 + 2^{-8})
(0, i + 1) i \not \in \{{0, 255}\} 2^{-16} (1 + 2^{-8})
(i + 1, 255) i \ne 254 2^{-16} (1 + 2^{-8})
(255, i + 1) i \not \in \{{1, 254}\} 2^{-16} (1 + 2^{-8})
(255, i + 2) i \not \in \{{0, 253, 254, 255}\} 2^{-16} (1 + 2^{-8})
(255, 0) i = 254 2^{-16} (1 + 2^{-8})
(255, 1) i = 255 2^{-16} (1 + 2^{-8})
(255, 2) i \in \{{0, 1}\} 2^{-16} (1 + 2^{-8})
(255, 255) i \ne 254 2^{-16} (1 + 2^{-8})
(129, 129) i = 2 2^{-16} (1 + 2^{-8})
==================== ========================================= =============================
قد تبدو هذه الجدولة مخيفة بعض الشيء في البداية. فقد يبدو تعبير الاحتمال في العمود
الأخير معقّدًا قليلًا، لكنّ هناك سببًا للتعبير عنها بهذه الطريقة. فلنفترض أنّ RC4 كانت
شيفرة تيار جيّدة، وأنّ جميع القيم ترد بالاحتمال نفسه. عندئذٍ كنتَ تتوقّع أن يكون
احتمال أيّ قيمة بايت بعينها هو 2^{-8}، لأنّ هناك 2^8 من قيم البايتات المختلفة.
وإذا كانت RC4 شيفرة تيار جيّدة، لكان لكلّ من بايتين متجاورين احتمال 2^{-8}،
فكان احتمال أيّ زوج من بايتين بعينه هو :math:2^{-8} \cdot 2^{-8} = 2^{-16}.
ولكّنّ RC4 ليست شيفرة تيار مثالية، فهذه الخصائص غير صحيحة. وبكتابة الاحتمال على
الصيغة 2^{-16} (1 + 2^{-k})، يصبح من الأسهل أن ترى مدى ابتعاد RC4 عمّا كنتَ
تتوقّعه من شيفرة تيار مثالية.
فلنحاول أن نقرأ السطر الأوّل من الجدول. فهو يقول إنّ البايت الأوّل i = 1 من أيّ
مقطع بطول 256 بايتًا مأخوذ من الشيفرة، إذا كان 0، فإنّ البايت الذي يليه يكون
أرجح إلى حدٍّ طفيف (وبوجه الدقّة، بمرّة و2^{-9}) أن يكون 0 مقارنةً بكونه أيّ
عدد آخر. ويمكننا أيضًا أن نرى أنّه عندما يكون أحد بايتات تدفّق المفاتيح 255،
يمكننا إجراء عدّة تنبّؤات حول البايت التالي، بحسب موضعه في تدفّق المفاتيح. فهو
أرجح أن يكون 0, 1, 2, 255، أو موضعه في تدفّق المفاتيح زائدًا واحدًا أو اثنين.
TODO: بيّن نجاح الهجوم
ومرةً أخرى، لا تسوء الهجمات بل تتحسّن فقط. وقد ركّزت هذه الهجمات في المقام الأوّل على الشيفرة نفسها، ولم تُحسَّن على نحو كامل لهجمات عملية على خدمات الويب مثلًا. ويمكن تحسين هذه الهجمات كثيرًا بمعلومة إضافية عن النصّ الصريح الذي تحاول استعادته. فمثلًا، غالبًا ما تكون كعكات HTTP مرمَّزة بترميز base-64 أو ست عشري."
ولا مفرّ من ذلك: فنحن بحاجة إلى التوقّف عن استعمال RC4. ولحسن الحظّ، فقد طوّرنا بدائل آمنة كثيرة. وقد أسهم التقدّم المستمرّ في التحليل التشفيري لـ RC4 في ترسيخ إحساس بالاستعجال بشأن تحسين البناءات التشفيرية المتاحة عادةً. وقد أدّى هذا، وعلى وجه الخصوص طوال سنة 2013، إلى تحسينات كبيرة في، مثلًا، تشفير المتصفّحات (وسنتحدّث عن تشفير المتصفّحات، ولا سيما SSL/TLS، في فصل لاحق)."
Salsa20
Salsa20 هي شيفرة تيار (stream cipher) أحدث صمّمها Dan Bernstein. وBernstein معروف
بأنّه كتب كثيرًا من البرمجيات مفتوحة المصدر (في النطاق العامّ)، معظمها إما متّصل
بالأمن مباشرةً أو مبنيّ مع مراعاة أمن المعلومات إلى حدٍّ كبير.
وهناك تنويعتان طفيفتان من Salsa20، تُسمّيان Salsa20/12 وSalsa20/8، وهما الخوارزمية نفسها إلّا أنّ فيه 12 و8 جولة على التوالي، نزولًا من أصل 20 جولة. وChaCha تعديل آخر متعامد لشيفرة Salsa20، يحاول زيادة مقدار الانتشار (diffusion) في كلّ جولة مع الحفاظ على الأداء أو تحسينه. ولا يحمل ChaCha الرقم «20» بعده؛ أمّا الخوارزميات المحدّدة فتحمل رقمًا بعدها (ChaCha8 وChaCha12 وChaCha20)، وهو يشير إلى عدد الجولات.
الجولات (rounds) هي تكرارات لدالة داخلية. وعادةً يلزم عدد من الجولات كي تعمل الخوارزمية بفاعلية؛ وغالبًا ما تبدأ الهجمات على نسخ الخوارزميات المخفَّضة الجولات. وتعدّ Salsa20 وChaCha من أفضل ما توصّل إليه علم شيفرات التيار الحديثة. ولا توجد حاليًا هجمات معروفة علنًا على Salsa20 أو ChaCha، ولا على أيّ من تنويعاتهما المخفَّضة الجولات الموصى بها، تكسر أمانهما العمليّ.
وعائلتا الشيفرة كلتاهما سريعتان إلى حدٍّ لا بأس به. فبالنسبة إلى التدفّقات الطويلة،
تستهلك Salsa20 نحو 4 دورات لكلّ بايت في النسخة الكاملة الجولات، ونحو 3 دورات لكلّ
بايت في نسخة الاثنتي عشرة جولة، ونحو دورتين لكلّ بايت في نسخة الثماني جولات، على
معالجات Intel الحديثة salsa20:speed ومعالجات AMD الحديثة cryptopp:bench. أمّا
ChaCha فأسرع قليلًا أيضًا (على معظم المنصّات). وللمقارنة، فإنّ هذا أسرع بأكثر من
ثلاثة أضعاف من RC4 [7]، وقرابة ثلاثة أضعاف من AES-CTR بمفتاح 128 بتًّا
عند 12.6 دورة لكلّ بايت، وهو في نطاق AES وضع GCM ([8]) مع تعليمات
عتاد مخصّصة.
ولدى Salsa20 خاصيتان مثيرتان للاهتمام بصفة خاصة. فأوّلًا، من الممكن «القفز» إلى
نقطة معيّنة في تدفّق المفاتيح من دون حساب جميع البتّات السابقة. وقد يكون ذلك مفيدًا،
مثلًا، إذا شُفِّر ملفّ كبير ورغبت في القدرة على إجراء قراءات عشوائية في منتصف الملفّ.
فبينما تشترط كثير من مخطّطات التشفير فكّ تشفير الملفّ بأسره، فإنّك مع Salsa20 تستطيع
ببساطة انتقاء الجزء الذي تحتاجه. وتُعدّ تركيبة أخرى لها هذه الخاصية وضع تشغيل
(mode of operation) يُسمّى CTR mode، وسنتحدّث عنه لاحقًا.
وهذه القدرة على «القفز» تعني أيضًا أنّ كتل Salsa20 يمكن حسابها بمعزل عن بعضها بعض، ما يسمح للتشفير أو لفكّ التشفير بالعمل على التوازي، ممّا قد يزيد الأداء على المعالجات متعدّدة النوى.
وثانيًا، فهي مقاومة لهجمات القنوات الجانبية (side-channel attacks) العديدة. ويتم ذلك بضمان ألّا تُستعمل مواد المفتاح يومًا ما للاختيار بين مسارات شيفرة مختلفة، وبضمان أنّ كلّ جولة تتكوّن من عدد ثابت من عمليات ذات زمن ثابت. والنتيجة أنّ كلّ كتلة تُنتَج بعدد عمليات متطابق تمامًا، بغضّ النظر عمّا إذا كان المفتاح.
وتستند شيفرتا التيار كليهما إلى تصميم ARX. وأحد مزايا شيفرات ARX أنّها بطبيعتها ذات زمن ثابت. فلا توجد أنماط وصول إلى الذاكرة سرّية قد تسرّب معلومات، كما في AES. وتؤدّي هذه الشيفرات أداءً جيّدًا على معماريات المعالجات الحديثة من دون الحاجة إلى تحسينات خاصّة بالشيفرة. فهي تستفيد من تعليمات المتّجهات العامة (generic vector instructions)، حيث يؤدّي المعالج عمليات متّصلة على قطع متعدّدة من البيانات في تعليمة واحدة. ونتيجةً لذلك، فإنّ أداء ChaCha20 ينافس أداء AES على معالجات Intel الحديثة، رغم أنّ للثانية عتادًا مخصّصًا.
وهذا مثال على عملية ARX:
x \leftarrow x \xor (y \madd z) \lll n
وللوصول إلى القيمة الجديدة لـx، نُجري أوّلًا جمعًا نمطيًّا (\boxplus) بين y
وz، ثمّ نُجري XOR (\xor) على الناتج مع x، وأخيرًا ندوّر إلى اليسار (\lll)
بمقدار n بتًّا. وهذه هي العملية الأساسية في جولة Salsa20.
شيفرات التيار الأصلية في مقابل أوضاع التشغيل
شيفرات التيار الأصلية في مقابل أوضاع التشغيل
تعدّ بعض النصوص شيفرات التيار الأصلية وحدها هي شيفرات التيار. وهذا الكتاب يركّز على
وظيفة الخوارزمية. وبما أنّ شيفرات الكتل في وضع تشغيل (mode of operation) وشيفرة
التيار الأصلية تأخذ مفتاحًا سرّيًا ويمكن استعمالها لتشفير تدفّق، وأنّ الاثنين
يستطيعان عادةً أن يحلّ كلّ منهما محلّ الآخر في نظام تشفير، فإنّنا نسمّي كليهما
ببساطة شيفرات تيار (stream cipher) وننتهي إلى ذلك.
وسنؤكّد أكثر على الصلة الوثيقة بين الاثنين من خلال CTR mode، وهو وضع تشغيل
ينتج شيفرة تيار متزامنة. وإذا كانت هناك أيضًا أوضاع تشغيل (مثل OFB وCFB) قادرة على
إنتاج شيفرات تيار ذاتية تزامن، فإنّها أقلّ شيوعًا بكثير ولا نتحدّث عنها هنا.
وضع CTR
يُعدّ CTR mode، اختصارًا لعبارة counter mode (وضع العدّاد)، وضع تشغيل يعمل بدمج
رقم فريد (nonce) مع عدّاد. ويُزاد العدّاد مع كلّ كتلة، ويُحشو بأصفار بحيث يصير كلّه
بطول حجم الكتلة. ثمّ تُمرَّر السلسلة الناتجة من الدمج على شيفرة كتلة. وتُستعمل
مخرجات شيفرة الكتل عندئذٍ كتدفّق مفاتيح.
CTR mode: يُشفَّر رقم فريد (nonce) واحد N مع عدّاد i محشو بالأصفار بواسطة
شيفرة الكتل لإنتاج كتلة تدفّق مفاتيح؛ ثمّ يُجرى على هذه الكتلة XOR مع كتلة النصّ
الصريح P_i لإنتاج كتلة النصّ المشفَّر C_i.
يوضّح هذا الرسم كتلة دخل واحدة N \| 00 \ldots \| i، وهي متكوّنة من رقم فريد
(nonce) هو N، ومن قيمة العدّاد الحالية i ومن الحشو، تُشفَّر بواسطة شيفرة الكتل
E باستعمال المفتاح k لإنتاج كتلة تدفّق المفاتيح S_i، ثمّ يُجرى عليها XOR مع
كتلة النصّ الصريح P_i لإنتاج كتلة النصّ المشفَّر C_i.
ومن الواضح أنّه لفكّ التشفير نفعل الشيء نفسه تمامًا، لأنّ إجراء XOR على بتّ بالقيمة
نفسها مرّتين يُنتج دائمًا البتّ الأصلي: p_i \xor s_i \xor s_i = p_i. ونتيجةً لذلك،
فإنّ تشفير CTR وفكّ تشفيره هما الشيء نفسه: في الحالتين تنتج تدفّق المفاتيح، ثمّ تُجري
XOR على النصّ الصريح أو النصّ المشفَّر للحصول على الآخر.
كي يكون CTR mode آمنًا، من الضروري ألّا تُعاد استعمال الأرقام الفريدة (nonces).
فإذا أُعيد استعمالها، فإنّ تدفّق المفاتيح كلّه سيتكرّر، ما يتيح للمهاجم تنفيذ هجمات
الوسادات متعدّدة المرّات.
وهذا يختلف عن متجه التهيئة (initialization vector) مثل المستعمل في CBC. فمتجه التهيئة
يجب ألّا يكون قابلًا للتنبّؤ. أمّا قدرة المهاجم على التنبّؤ برقم فريد (nonce) في وضع
CTR فليست مهمّة إلى هذا الحدّ: فدون المفتاح السرّي لا يعرف على أيّ حال ما سيكون عليه
مخرج شيفرة الكتل (أي السلسلة في تدفّق المفاتيح).
وكما في Salsa20، تمتلك CTR mode الخاصية المثيرة بأنّك تستطيع القفز بسهولة إلى أيّ
نقطة في تدفّق المفاتيح: يكفي أن تزيد العدّاد إلى تلك النقطة. ويشرح
فقرة Salsa20 عن هذا الموضوع <keystream jump> لماذا قد يكون ذلك مفيدًا.
وثمّة خاصية أخرى مثيرة: بما أنّ أيّ كتلة في تدفّق المفاتيح يمكن حسابها بمعزل تامّ عن أيّ كتلة أخرى، فإنّ التشفير وفكّ التشفير كليهما سهلان جدًّا في الحساب على التوازي.
هجمات قلب البتّات في شيفرات التيار
شيفرات التيار المتزامنة (synchronous)، مثل شيفرات التيار الأصلية أو شيفرة كتلة في
CTR mode، معرَّضة أيضًا لهجوم قلب البتّات. وهو مشابه لهجمات قلب البتّات في وضع
CBC من حيث أنّ المهاجم يقلب عدة بتّات في النصّ المشفَّر، فيؤدّي ذلك إلى قلب بعض
البتّات في النصّ الصريح.
وهذا الهجوم في الواقع أسهل بكثير تنفيذه على شيفرات التيار (stream cipher) ممّا هو
عليه في وضع CBC. فأوّلًا، البتّ المقلوب في النصّ المشفَّر يؤدّي إلى قلب البتّ نفسه
في النصّ الصريح، لا إلى البتّ المقابل في الكتلة التالية. وإضافةً إلى ذلك، فإنّه لا
يؤثّر إلّا في ذلك البتّ؛ إذ إنّ النصّ الصريح للكتلة المعدَّلة يختلط في هجمات قلب
البتّات في وضع CBC. وأخيرًا، بما أنّ المهاجم يعدّل تسلسل بايتات لا تسلسل كتل، فإنّ
الهجمات لا تحدّها حدود حجم الكتلة المحدّد. فعلى سبيل المثال، في هجمات قلب البتّات
في وضع CBC يستطيع المهاجم تعديل كتلة واحدة، لكنّه لا يستطيع تعديل الكتلة المجاورة.
TODO: أضف رسمًا توضيحيًّا
وهذا مثال آخر على لماذا يجب أن تمشي المصادقة مع التشفير جنبًا إلى جنب. فإذا صُدِّقت الرسالة على نحو صحيح، استطاع المستقبِل ببساطة رفض الرسائل المعدَّلة، وضاع أثر الهجوم.
أوضاع التشغيل المصادِقة
هناك أوضاع تشغيل أخرى توفّر المصادقة والتشفير معًا في آنٍ واحد. وبما أنّنا لم نتحدّث عن المصادقة البتّة حتى الآن، فسننتاولها لاحقًا.
المشكلات المتبقّية
لدينا الآن أدوات تشفّر تدفّقات كبيرة من البيانات باستعمال مفتاح صغير. لكنّنا لم
نتحدّث فعليًّا بعد عن كيفية الاتفاق على ذلك المفتاح. وكما أُشير في فصل سابق، فإنّ
التواصل بين n من الناس يتطلّب \frac{n(n-1)}{2} من عمليات تبادل المفاتيح. وينمو
عدد عمليات تبادل المفاتيح بسرعة تقارب مربّع عدد الناس squared. وبينما صار المفتاح
المراد تبادله أصغر بكثير ممّا كان عليه مع وسادات المرّة الواحدة، فإنّ المشكلة
الجوهريّة المتمثّلة في العدد المستحيل من عمليات تبادل المفاتيح لم تُحلّ بعد. وسنعالج
هذه المشكلة في القسم التالي، حيث سننظر في بروتوكولات تبادل المفاتيح: وهي بروتوكولات
تسمح لنا بالاتفاق على مفتاح سرّي عبر وسيط غير آمن.
وإضافةً إلى ذلك، رأينا أنّ التشفير وحده لا يكفي لتوفير الأمن: فبدون مصادقة، يكون من السهل على المهاجمين تعديل الرسالة، بل وفي أنظمة معيبة كثيرة حتّى فكّ تشفيرها. وفي فصل قادم، سنتحدّث عن كيفية مصادقة الرسائل لمنع المهاجمين من تعديلها.
هذا العرض التوضيحي بعينه لا يعمل إلّا على خرائط البتّات غير المضغوطة. أمّا الوسائط الأخرى فالأثر ليس أقلّ ضررًا بكثير: إنّه أقلّ ظهورًا فحسب. ↩︎
تُمثَّل أوضاع التشغيل تقليديًّا بثلاثة أحرف (acronym). ↩︎
الهندسة الاجتماعية تعني خداع الناس للقيام بأشياء لا ينبغي أن يفعلوها، مثل تسليم مفاتيح سرّية أو تنفيذ عمليات معيّنة. وهي عادةً أكثر وسيلة فاعلية لكسر الأنظمة التشفيرية الآمنة. ↩︎
عذرًا على التورية. ↩︎
من الناحية الفنية، لا يُعرَّف حشو PKCS#5 إلّا لأحجام كتل مقدارها 8 بايتات، لكنّ الفكرة تعمَّم بسهولة واضحة، وهي كذلك المصطلح الأكثر استعمالًا. ↩︎
نستعمل هنا
\|معامِلا للدمج. وتشمل الرموز الأخرى الشائعة للدمج+(في بعض لغات البرمجة، مثل Python) و⋅ (في اللغات الصورية). ↩︎لا تذكر الاختبارات المقتبَسة RC4 وإنّما MARC4، وهو اختصار لعبارة «RC4 المزعومة المعدَّلة» (modified alleged RC4). ويشرح قسم RC4 لماذا هي «مزعومة»، و«معدَّلة» تعني أنّها تتخلّص من أوّل 256 بايت بسبب نقطة ضعف في RC4. ↩︎
وضع GCM(GCM mode) هو وضع تشفير مصادق، وسنراه بمزيد من التفصيل في فصل لاحق. ↩︎