Nov 20, 2010

Cryptography ตอนที่ 3 การเข้ารหัสลับแบบจับคู่

การเข้ารหัสลับด้วยวิธีต่อมานั้นก็คือ Substitution Cipher หรือแบบจับคู่
วิธีการก็ไม่รู้ว่าจะอธิบายให้ยุ่งยากทำไมเนาะ - -"
แต่ก็เอาถอะ ไหนๆ ก็พูดในเชิงคณิตศาสตร์ละ งั้นก็ลงอธิบายแบบคณิตศาสตร์เลยละกัน

ให้ P = C = Z26, ส่วน K คือวิธีเรียงสับเปลี่ยนของเลข 0 ถึง 25 ทั่งหมดที่เป็นไปได้ ให้ ? เป็นสมาชิกของ K จะกล่าวว่า
e?(x) = ?(x) และ d?(x) = ?-1(x) เมื่อ ?-1 คืออินเวอร์สของ ?

จะเห็นว่า วิธีนี้ให้ key space ที่ใหญ่มากถึง 26! หรือประมาณ 4.03 x 1026 เลยทีเดียว (แต่ก็ยังไม่ปลอดภัยอยู่ดี!)

จุดที่อาจเสียเวลาหน่อยคือตอนสร้าง key ขึ้นมา เพราะต้องเรียงสับเปลี่ยนตัวเลขถึง 26 ตัว
งั้นก็ต้องใช้เครื่องทุ่นแรงกันหน่อยหละ ก่อนอื่นก็สร้างลิสต์ของเลข 26 ตัวขึ้นมาก่อน

>>> list = []
>>> for i in range(26):
... list.append(i)
...


ต่อมาเราจะสับเปลี่ยนเลขพวกนี้แล้ว วิธีที่ง่ายที่สุดคือไล่สลับตำแหน่งที่สนใจกับตำแหน่งสุ่มไปเรื่อยๆ จนครบ
ถึงแม้ว่าการใช้วิธีนี้จะครอบคลุมการเรียงสับเปลี่ยนทุกรูปแบบก็ตาม แต่ข้อเสียคือความน่าจะเป็นจะไม่เท่าการเรียงสับเปลี่ยนจริงๆ นะครับ

>>> import random
>>> for i in range(26):
... temp = random.randint(0, 25)
... list[i], list[temp] = list[temp], list[i]
...


จัดการเปลี่ยนมันให้เป็นตัวอักษร และเซฟเป็นไฟล์ *.txt ซะ (เพราะต้องได้ใช้ในอนาคตแน่นอน!)

>>> mapping = ""
>>> for i in range(26):
... mapping += chr(list[i] + ord('A'))
...
>>> f = open("map_key.txt", 'w')
>>> f.write(mapping)
>>> f.close


ตอนนี้ เราจะได้ไฟล์ map_key.txt ออกมา ซึ่งบรรจุการจับคู่ของตัวอักษรแล้วครับ
สำหรับการจับคู่ของผมในครั้งนี้ (ไล่จาก a ไป z) คือ XLNYKIHFJWTRBMVPGSAUZQECOD
ต่อมา เช่นเดียวกับที่เราได้เขียนฟังก์ชันไว้ใช้ในตอนที่แล้ว คราวนี้เราจะเปิดไฟล์เดิมมาเขียนเพิ่ม ดังนี้ครับ

def substitution(pain_text, key_file):
cipher_text = ""
mapping = []
for i in range(26):
mapping.append(0)
f = open(key_file)
for i in range(26):
mapping[i] = upper_to_number(f.read(1))
f.close()
for i in range(len(pain_text)):
char_num = lower_to_number(pain_text[i])
char_num = mapping[char_num]
cipher_text += number_to_upper(char_num)
print(cipher_text)

def upper_to_number(text):
return(ord(text) - start_upper)


เสร็จเรียบร้อย ลองเรียกใช้ฟังก์ชันโดยการ import encrypt เข้ามาก่อน
และเรียกที่อยู่ฟังก์ชัน encrypt.substitution("canyoureadme", "map_key.txt ")
ก็ได้ผลลัพท์เป็น NXMOVZSKXYBK ครับ

AKKOVZMKCUUJBK