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

التشفير باستخدام شيفرة التحويل:

شيفرة قيصر ليست شيفرة آمنة لأنه يمكن فكها باستخدام تقنية القوة الغاشمة من خلال المرور على كل القيم الممكنة ال 26 لمفتاح التشفير.

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

قبل البدء بكتابة الكود، لنقم بتشفير الرسالة ‘Common sense is not so common.’ باستخدام الورقة والقلم وبشكل يتضمن الفراغات وعلامات الترقيم، هذا يعني أن الرسالة مكونة من 30 حرف. سوف نستخدم الرقم 8 كمفتاح.

أول خطوة هي رسم عدد من الصناديق مساوي لقيمة المفتاح (ثمانية صناديق في هذا المثال)

Transposition

ثاني خطوة هي كتابة الرسالة المراد تشفيرها في داخل الصناديق، كل حرف في صندوق

تذكر أن المسافة الفارغة تعتبر حرف ( قمنا بكتابة (S) للإشارة إلى المسافة الفارغة لكي لا تبقى صناديق فارغة)

Transposition2

نحن نملك فقط 8 صناديق ولكن الرسالة المراد تشفيرها مكونة من 30 حرف لذلك سوف نقوم برسم ثمانية صناديق أخرى تحت الصناديق الأولى ونقوم بكتابة بقية الأحرف في داخلها

Transposition3

قمنا بتظليل آخر صندوقين من أجل تجاهلهم حيث النص المشفر هو الأحرف التي تقرأ من الأعلى إلى الأسفل لكل عمود

‘C’ , ‘e’ , ‘n’ , ‘o’ هذه الأحرف من العمود الأول بعدها ننتقل لأحرف العمود الثاني ثم الثالث وهكذا حتى نهاية العواميد

النص المشفر هو قراءة الأحرف من الأعلى إلى الأسفل ثم الانتقال إلى العمود الثاني

‘o’ , ‘n’ , ‘o’ , ‘m’

ويتم تجاهل الصناديق المظللة.

النص المشفر هو ‘Cenoonommstmme oo snnio s s c’

وهو ممزوج بشكل كاف لمنع أي شخص من معرفة نص الرسالة الأصلية من خلال النظر إلى الرسالة المشفرة.

خطوات عملية التشفير:

  1. تحديد عدد أحرف الرسالة واختيار قيمة مفتاح التشفير
  2. رسم عدد من الصناديق مساوي لقيمة مفتاح التشفير
  3. ملئ الصناديق بأحرف الرسالة من اليسار إلى اليمين
  4. عند امتلأ الصناديق وعدم انتهاء أحرف الرسالة يتم إضافة سطر جديد من الصناديق
  5. تظليل الصناديق الفارغة في نهاية الصناديق
  6. كتابة الرسالة المشفرة من خلال قراءة الأحرف من الأعلى إلى الأسفل وعند الانتهاء من أول عمود ننتقل إلى العمود المجاور ويتم تجاهل الصناديق المظللة

برنامج التشفير باستخدام شيفرة التحويل:

التشفير باستخدام الورق والقلم يتطلب الكثير من الجهد ويمكن أن نقع بأخطاء كتابية أثناء عملية التشفير.

لنبدأ بكتابة برنامج يقوم بعملية التشفير باستخدام شيفرة التحويل ( برنامج فك التشفير سوف يتم شرحه في المقال القادم إن شاء الله)

عند استخدام هذا البرنامج سوف تظهر مشكلة بسيطة، إذا كانت المسافات الفارغة في نهاية النص المشفر فلن نتمكن من رؤية هذه المسافات أو لن نتمكن من معرفة عدد هذه المسافات ومن أجل حل هذه المشكلة فإن البرنامج سوف يضيف الرمز | في نهاية النص المشفر (الرمز | موجود في لوحة المفاتيح فوق زر Enter).

Transposition4

الكود البرمجي لبرنامج الشفير باستخدام شيفر التحويل:

قم بفتح ملف جديد من خلال File > New File ثم قم بكتابة الكود التالي في داخله ثم قم بحفظه باسم transpositionEncrypt.py واضغط F5 من أجل تنفيذ هذا البرنامج

يجب أن تقوم أولاُ بوضع الوحدة pyperclip.py في نفس المجلد الذي سوف تقوم بحفظ البرنامج في داخله، يمكنك الحصول على pyperclip.py module من خلال هذا الرابط.

Transposition5

Transposition6

نتيجة تنفيذ هذا البرنامج هي:

Transposition7

النص المشفر (بدون الرمز | )  تم نسخه إلى الذاكرة ويمكنه لصقه في أي ملف نصي أو في رسالة إيميل لتقوم بإرساله إلى أي شخص تريد.

إذا كنت تريد تشفير رسالة مختلفة أو استخدام مفتاح تشفير مختلف قم بتغير القيم المسندة للمتغيرات myMessage and myKey في السطرين 7 and 8

كيف يعمل هذا البرنامج:

Transposition8

في برنامج التشفير باستخدام شيفرة التحويل وبشكل مماثل لبرنامج شيفرة قيصر سيتم نسخ النص المشفر إلى الذاكرة لذلك قمنا باستيراد الوحدة pyperclip لنتمكن من استدعاء التابع pyperclip.copy()

خلق تابع باستخدام التعليمة def:

Transposition9

التابع main() في البرنامج:

Transposition10

في السطرين 7 و 8 تم تعريف المتغيرين myMessage and myKey حيث سيتم تخزين النص الصريح (النص الغير مشفر) ومفتاح التشفير في هذين المتغيرين

Transposition2-2

الكود الذي سوف يقوم بعملية التشفير قمنا بوضعه داخل تابع يتم تعريفه في السطر 21 باسم encryptMessage()

هذا التابع سوف يمرر له قيمتين:

  • قيمة عددية (عدد صحيح) وهي قيمة المفتاح
  • وقيمة نصية وهي الرسالة المراد تشفيرها

عند استدعاء هذا التابع يتم الفصل بين القيم الممررة إلية باستخدام فاصلة ‘ , ‘

القيمة التي يعيدها التابع encryptMessage() هي قيمة نصية وهي النص المشفر.

كود هذا التابع سوف يتم شرحه لاحقاً في هذا المقال.

القيم التي يعيدها هذا التابع سوف يتم تخزينها في المتغير ciphertext

Transposition11

الرسالة المشفرة سوف يتم طباعتها على الشاشة في السطر 15 ويتم نسخها إلى الذاكرة ، في السطر 15 البرنامج يقوم بطباعة الرمز ‘ | ‘ في نهاية الرسالة المشفرة لكي يتمكن المستخدم من معرفة إذا كان يوجد فراغات في نهاية السلسة المشفرة.

السطر 18 هو آخر سطر في جسم التابع main() وبعد تنفيذه سوف يعود البرنامج لتنفيذ السطر الذي يلي سطر استدعاء هذا التابع.

استدعاء التابع main() هو في السطر 45 في نهاية البرنامج لذلك بعد الانتهاء من تنفيذ آخر سطر من التعليمات الخاصة بهذا التابع سوف ينتهي البرنامج.

البارامترات:

Transposition12

التابع الذي يقوم بعملية التشفير  encryptMessage() يأخذ بارامترين.

البارامترات : هي متغيرات تحوي على قيم يتم تمريرها إلى التابع عند استدعاءه.

البارامترات يتم حذفها بشكل أتوماتيكي بعد تنفيذ التابع.

عندما يتم استدعاء التابع encryptMessage() في السطر 10 ، يتم تمرير قيمتين له  القيمتان الموجودتان في المتغيران (myKey and myMessage)

هذه القيم تسند إلى البارامترات key and message (التي يمكن أن تراها في السطر 21)

البارامتر: هو اسم المتغير الموجود بين القوسين ( ) الخاصين بالتابع.

البايثون سوف يظهر رسالة خطأ إذا قمت بتمرير قيم أكثر أو أقل من عدد البارامترات التي يملكها التابع

القائمة List :

Transposition13

في السطر 23 قمنا باستخدام نوع جديد من البيانات يسمى القائمة list ، القائمة يمكن أن تحوي على عدة قيم، وبشكل مماثل للسلسلة النصية التي تبدأ وتنتهي بعلامة التنصيص فإن القائمة تبدأ وتنتهي بالقوسين [ ] ويتم وضع القيم المراد حفظها داخل هذين القوسين ويتم الفصل بين هذه القيم باستخدام الفاصلة ‘ , ‘ كل قيمة داخل القائمة تسمى مادة item.

القوائم مفيدة جداً عندما نريد تخزين الكثير من القيم ولا نريد خلق متغير لكل قيمة.

العديد من العمليات يمكن أن تعمل مع القوائم مثل الفهرسة indexing والاقتطاع slicing 

دليل الفهرسة يشير إلى المادة داخل القائمة.

تذكر أن دليل الفهرسة يبدأ بالقيمة 0 وليس القيمة 1

يمكن استخدام الحلقة for من أجل المرور على كل القيم الموجودة في القائمة

كما أن علامات التنصيص الفارغة كانت تعبر عن سلسلة نصية فارغة فإن القوسين [] الفارغين يمثلان قائمة فارغة.

خوارزمية شيفرة التحويل:

يجب أن نقوم بتحويل الخطوات التي قمنا بها باستخدام الورقة والقلم إلى كود بلغة البايثون

  • النص المراد تشفيره ‘Common sense is not common. ‘
  • مفتاح التشفير 8

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

Transposition14

دليل الفهرسة لكل حرف في الصناديق (تذكر أن الفهرسة تبدأ من الرقم 0 وليس من الرقم 1)

Transposition15

من هذه الصناديق يمكننا أن نرى:

العمود الأول له قيم الفهرسة 0, 8, 16, 24 وهي للأحرف C, e, n, o

العمود الثاني له قيم الفهرسة 1, 9, 17, 25 وهي للأحرف o, n, o, m

ويمكن أن نستنتج بأن العمود رقم n سوف يكون له قيم الفهرسة 0+n, 8+n, 16+n, 24+n

Transposition16

لماذا اخترنا الأرقام 0, 8, 16, 24 ؟

هذه الأرقام حصلنا عليها من إضافة قيمة المفتاح (الرقم 8 في هذا المثال) ابتداءً من الرقم 0

0+8=8,  8+8=16,  16+8=24

24+8=32 ولكننا لم نستخدم هذه القيمة لأنها أكبر من عدد أحرف الرسالة ولهذا السبب توقفنا عند الرقم 24

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

Transposition17

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

(في هذا المثال القائمة سوف تحوي على 8 سلاسل نصية لأن مفتاح التشفير هو 8)

Transposition18

[ciphertext[0 هو العمود الأول من اليسار

[ciphertext[1 هو العمود الثاني وهكذا

السلاسل النصية سوف تحوي على كل الأحرف الموجودة داخل كل عمود

Transposition19

المتغير ciphertext الخاص بهذه الشبكة سيكون كالتالي:

Transposition20

أول خطوة لخلق هذه القائمة هي خلق عدة سلاسل نصية فارغة بعدد الأعمدة ( قيمة مفتاح التشفير)، يمكننا استخدام عملية التكرار من أجل تكرار سلسلة نصية فارغة عدد من المرات بحسب قيمة مفتاح التشفير.

وهذه ما يتم حسابه في السطر 23

Transposition21

الخطوة التالية هي إضافة نص إلى كل سلسلة نصية في القائمة ciphertext

الحلقة for في السطر 26 تقوم بالدوران على كل عمود حيث أن المتغير col سوف يملك قيم تستخدم في الفهرسة في ciphertext

المتغير col سوف يبدأ بالقيمة 0 من أجل أول دورة للحلقة for ثم القيمة 1 من أجل ثاني دورة للحقلة for وهكذا.

وبهذه الطريفة فإن ciphertext[col] سوف تمثل السلسلة النصية الموجودة في العمود ذو الرقم col

أما المتغير pointer فسوف يستخدم في الفهرسة للقيمة النصية المحفوظة في المتغير message ، وفي كل دورة من حلقة for فإن قيمة pointer سوف تبدأ بنفس قيمة col (كما في السطر 27)

Transposition22

في داخل الحلقة for التي تبدأ في السطر 26 قمنا بتعريف حلقة while والتي تبدأ في السطر 30 ، من أجل كل عمود نريد المرور على المتغير message ونلتقط كل حرف دليله هو من مضاعفات قيمة مفتاح التشفير.

في السطر 27 ومن أجل أول دورة للحلقة for كانت قيمة pointer هي 0

طالما أن قيمة pointer هي أصغر من طول الرسالة، نريد أن يتم إضافة الحرف message[pointer] (الحرف الذي دليل الفهرسة الخاص به هو pointer وهو في هذه الحالة الحرف الأول من الرسالة لأن دليل الفهرسة هو 0) إلى نهاية السلسة النصية ذات الرقم col داخل القائمة ciphertext

ثم نقوم بإضافة 8 (قيمة مفتاح التشفير) إلى قيمة pointer في كل مرة تتكرر فيها الحلقة (السطر 36)

  • في أول دورة للحلقة حصلنا على الحرف [message[0
  • في ثاني دورة للحلقة حصلنا على الحرف [message[8
  • في ثالث دورة للحلقة حصلنا على الحرف [message[16
  • في رابع دورة للحلقة حصلنا على الحرف [message[24

ويتم إضافة هذه الأحرف إلى نهاية السلسلة النصية ciphertext[col] (بما أن col = 0 من أجل أول دورة للحلقة هذا يعني [ciphertext[0).

Transposition23

الشكل السابق يظهر كل أحرف الرسالة مع دليل الفهرسة الخاص بكل حرف كما يظهر الأحرف التي تم اختيارها في أو دورة لحلقة for وعند جمع هذه الأحرف مع بعضها سوف نحصل على ‘Ceno’ وهي السلسلة النصية الأولى في القائمة ciphertest

Transposition24

في الدورة الثانية لحلقة for تصبح قيمة المتغير col = 1 (بدلاً من 0)

وتصبح قيمة المتغير pointer = 1 والآن وعند إضافة قيمة المفتاح ( 8 ) إلى pointer ضمن حلقة while في السطر 30 فسوف نحصل على قيم الفهرسة 1, 9, 17, 25

Transposition25

[message[1], message[9], message[17], message[25

هذه الأحرف هي مكونات السلسلة النصية الثانية في القائمة ciphertext وهي ciphertext[1] = ‘onom’ (وهو العمود الثاني)

عندما تنتهي حلقة for بعد أن تمر على كل العواميد سوف تصبح قيمة القائمة

ciphertext = [‘Ceno’ , ‘onom’ , ‘me o’ , ‘o sn’ , ‘nio.’ , ‘ s ‘ , ‘s c’]

سوف نستخدم الطريقة النصية join() string method من أجل تحويل هذه السلاسل النصية إلى سلسلة نصية واحدة.

الطريقة النصية join() :

الطريقة join() تم استخدامها في السطر 39 من كود البرنامج.

هذه الطريقة تأخذ قائمة من السلاسل النصية وتعيد سلسلة نصية وحيدة هي عبارة عن مجموع هذه السلاسل مع بعضها البعض.

استدعاء هذه الطريقة يجب أن يكون بين السلاسل والقائمة (سوف نستخدم سلسلة نصية فارغة من أجل الاستدعاء)

Transposition26

قمنا باستدعاء الطريقة join() على سلسلة نصية فارغة ومررنا لها المتغير ciphertext ليتم جمع السلاسل النصية الموجودة في هذا المتغير مع بعضها البعض (بدون أي فراغات بينها)

التابع أو الطريقة دائماً يتم استدعائهم من أجل حساب قيمة وهذه القيمة تسمى القيمة المٌعادة (القيمة التي يعيدها التابع أو الطريقة) return value

قمنا بخلق التابع باستخدام التعليمة def كما قمنا باستخدام التعليمة return من أجل اخباره بالقيمة التي يجب عليه إعادتها.

التعليمة return تتبع باسم المتغير المراد إعادة قيمته أو يمكن أن تتبع بعبارة جبرية بدلاً من اسم المتغير وفي هذه الحالة يتم إعادة القيمة بعد حساب العبارة الجبرية.

المتغير الخاص __name__:

Transposition27

يمكننا تشغيل برنامجنا في الوحدة module باستخدام اسم المتغير الخاص __name__

عندما يعمل برنامج البايثون هناك متغير خاص __name__ (خطين قبل الاسم وخطين بعده) الذي يتم إسناد القيمة النصية ‘__main__’ له وذلك قبل أول سطر من برنامجك.

في نهاية ملف السكريبت script file وبعد كل تعليمة def نقوم بكتابة بعض التعليمات التي تقوم بفحص فيما إذا كانت قيمة __name__ هي القيمة النصية ‘__main__’ وإذا كان ذلك محققاً نقوم باستدعاء التابع.

التعليمة if في السطر 44 يتم تنفيذها كأول سطر من الكود عند الضغط على F5 (طبعاً بعد تنفيذ تعليمة import في السطر 4 والتعليمة def في السطرين 6 and 21)

السبب لكتابتنا لهذا الكود بهذه الطريقة لأن البايثون يقوم بإسناد القيمة ‘__main__’ إلى المتغير __name__  عند تشغيل البرنامج أو يقوم بإسناد القيمة ‘transpositionEncryp’ إلى المتغير __name__ إذا تم استيراد هذا البرنامج من قبل برامج أخرى.

بهذه الطريقة يستطيع البايثون معرفة فيما إذا كان هذه البرنامج بدأ العمل كبرنامج مستقل أو تم استيراده من قبل برامج أخرى كما في الوحدات module

بشكل مماثل للطريقة التي يقوم برنامجنا باستيراد الوحدة pyperclip من أجل أن نتمكن من استدعاء التوابع الموجودة في داخلها فهناك برامج يمكن أن تقوم باستيراد برنامجنا من خلال التعليمة import transpositionEncrypt.py من أجل أن تتمكن من استدعاء التابع encryptMessage()

عندما يتم تنفيذ التعليمة import فإن البايثون يقوم بالنظر إلى الملف (الوحدة ) module من خلال اللاحقة ‘ .py ‘ في نهاية اسم الملف (وهذه هو سبب أن التعليمة import pyperclip تقوم باستيراد الملف pyperclip.py)

عندما يقوم البايثون باستيراد ملف فسوف يتم اسناد اسم هذا الملف إلى المتغير __name__ وثم يبدأ البرنامج بالعمل.

عندما يتم استيراد برنامجنا transpoitionEncrypt.py نريد لكل تعليمات def أن تعمل (من أجل تعريف التابع encryptMessage() الذي نريد استدعاءه) ولكننا لا نريد استدعاء التابع main() لأنه يقوم بتنفيذ كود التشفير للسلسلة النصية

‘Common sense is not so common.’ باستخدام المفتاح 8

وهذه هو سبب وضعنا الكود داخل تابع (التابع main()) ثم قمنا بإضافة أخر سطرين في البرنامج من أجل استدعاء هذا التابع، عندما نقوم بهذه الأمور فإن برنامجنا يمكن أن يعمل كبرنامج مستقل ويمكن أن يعمل أيضاً كوحدة module لبرنامج أخر.

حجم المفتاح وطول الرسالة:

لاحظ ماذا يحدث عندما يكون طول الرسالة أقل من ضعفي المفتاح

Transposition28

عند استخدام المفتاح 25 لتشفير الرسالة ‘Common sense is not so common.’ فسوف نحصل على الرسالة المشفرة ‘Cmommomno.n sense is not so co’ يوجد جزء من الرسالة لم يتم تشفيره !

هذا يحدث عندما يكون حجم المفتاح أكبر من ضعفي طول الرسالة وفي هذه الحالة سوف يوجد على الأقل حرف وحيد في العامود وسوف يتم عرضه في الرسالة المشفرة كما هو في الرسالة الأصلية قبل عملية التشفير.

وبسبب ذلك فإن المفتاح في شيفرة التحويل يجب أن يكون أقل من نصف طول الرسالة المراد تشفيرها.

كلما كانت الرسالة أطول يوجد عدد أكبر من مفاتيح التشفير الممكنة لتشفيرها باستخدام شيفرة التحويل.

في المقال القادم إنشاء الله سوف نقوم بكتابة برنامج بلغة البايثون ليقوم بفك شيفرة التحويل.