شيفرة قيصر

كان غايوس يوليوس قيصر يواجه خطر تسرّب المعلومات في رسائله العسكرية إذا وقعت في أيدي العدو. فاستعمل حيلة لتشفير مضمونها: أمر الكتاب بتبديل كل حرف في النص بحرف آخر يليه بعدد معيّن من الخانات. هذه الطريقة أصبحت تُعرف اليوم باسم شيفرة قيصر وهي نوع من شيفرة الإزاحة (Shift Cipher).

التعمية، أو التشفير (Cryptography)، تهتم بتأمين التواصل بوجود أشخاص آخرين قد يحاولون قراءة الرسائل الخاصة. نُحوّل البيانات من شكلها الطبيعي المفهوم إلى شكل غير مفهوم، بحيث يحتاج من يقرؤها إلى معرفة سر ما ليستعيد فحواها. في شيفرة قيصر، هذه المعرفة هي مقدار الإزاحة (shift).

فإذا كان مقدار الإزاحة 3 مثلًا يصير:

  • حرف a يصير d.
  • حرف b يصير e.
  • حرف c يصير f.

وأما الحروف الأخيرة فتدور، فيكون:

  • حرف x يصير a.
  • حرف y يصير b.
  • حرف z يصير c.

رسالة قبل التعمية وبعدها بإزاحة 3، واستعادتها بإزاحة سالبة

سنبني الخوارزمية على حرف واحد أولًا، ثم نستعملها لتعمية نص كامل.

موضع الحرف

نبدأ بتعريف سلسلتي الأحرف الإنجليزية؛ واحدة للأحرف الصغيرة، وأخرى للكبيرة:

تذكّر أن لدينا في بايثون الفعل str.index، الذي يأخذ جزءًا نصيًّا ويبحث عن موضعه في النص. سنستعمله لمعرفة موضع الحرف داخل الأبجدية:

الموضع الأول 0، والأخير 25. فإذا أضفنا الإزاحة 3 إلى موضع a حصلنا على 3، وهو موضع d. لكن إضافة 3 إلى موضع z تعطينا 28، وليس لدينا حرف في هذا الموضع. نحتاج إلى تدوير الموضع ليعود إلى أول الأبجدية.

تدوير المواضع

الأمر الآخر الذي سيفيدنا هو الحسابيات المقاسية: تتحرّك الأرقام بالجمع ونحوه، وتلتف عند الوصول إلى قيمة معيّنة تسمى القياس.

نتتبّع إزاحة الحرف z ثلاث خطوات:

هذه العملية في بايثون هي %، وتعطي باقي القسمة. عدد مواضع الأبجدية 26؛ لذلك نضيف الإزاحة، ثم نأخذ باقي القسمة على 26 لنعيد الناتج إلى المواضع من 0 إلى 25:

الناتج 2، وهو موضع c. نطبّق الحساب نفسه مع استعمال index لمعرفة موضع الحرف وlen لمعرفة طول الأبجدية:

الناتج هو الموضع 2 والحرف c: زدنا الموضع، ثم أعدناه إلى نطاق الأبجدية، ثم أخذنا الحرف الذي يشغله.

تعمية حرف واحد

نكتب الدالة encode التي تأخذ حرفًا في char ومقدار الإزاحة في shift، وتعيد الحرف البديل:

نختبر الدالة ببعض التوكيدات. إذا نجحت فلن يظهر خطأ:

استعادة الحرف

دالة decode تعكس التعمية: تزيح الحرف في الاتجاه المعاكس. إذا عمّينا بإزاحة 3، نستعيد الحرف بإزاحة -3.

الدالة encode تقبل إزاحة سالبة أصلًا، و% يعيد الموضع إلى نطاق الأبجدية حتى إذا صار سالبًا. لذلك لا نحتاج إلى تكرار حساب الموضع؛ نستدعي encode بسالب الإزاحة:

للتأكد من أن decode تعكس encode، نمرّر إليها ناتج التعمية بالإزاحة نفسها:

تعمية نص كامل

بعد أن عملت encode على مستوى الحرف، نستعملها لكل حرف في النص:

أما استعادة النص فباستعمال decode بدلًا من encode في الحلقة نفسها:

رسالة كاملة

أخيرًا نجرّب على الفقرة الظاهرة في الرسم، ثم نستعيدها:

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

خلاصة

نحوّل الحرف إلى موضع باستخدام index، ثم نضيف الإزاحة وندوّر الموضع باستخدام %، ثم نأخذ الحرف البديل. واستعادة الحرف هي التعمية نفسها بإزاحة سالبة؛ لذلك تستعمل decode الدالة encode بدل كتابة خوارزمية أخرى. ولتعمية نص كامل أو استعادته، نكرّر العملية على حروفه.