Dec 3, 2010

Cryptography ตอนที่ 5 การเข้ารหัสลับวิจเญอแนร์

เราจะเห็นว่าการเข้ารหัสลับในสามตอนที่ผ่านมานั้น จะจับคู่จากอักษรไปยังอักษรตัวเดิมเสมอ
ซึ่งนั่นส่งผลให้เราใช้วิธีง่ายๆ คือไล่แทนอักษรไปเรื่อยๆ (brute force) ได้ แม้ว่ามันจะกินเวลาก็ตาม
เราเรียกวิธีเข้ารหัสจากทั้งสามตอนนั้นว่าเป็นแบบ monoalphabetic หรือแบบอักษรตายตัวครับ

ในปี 1553 จึงได้มีการคิดค้นวิธีเข้ารหัสลับแบบ polyalphabetic หรือแบบอักษรไม่ตายตัวขึ้น
ผู้คิดค้นคือ Giovan Battista Bellaso แต่เนื่องด้วยเหตุผลทางประวัติศาสตร์ในช่วงศตวรรษที่ 19
ทำให้ผู้ที่ได้รับเครดิทกลายเป็น Blaise de Vigen?re แทน เราจึงรู้จักวิธีนี้ในชื่อ Vigen?re Cipher

ข้อดีของการเข้ารหัสลับด้วยวิธีนี้คือ เข้ารหัสง่าย แต่โจมตีรหัสยาก (อย่างน้อยถ้าไม่มีคอมฯ)
ขั้นตอนการเข้ารหัสก็ง่ายเหลือหลายอย่างที่ว่ามา แค่เลือกชุดตัวเลขที่จะใช้เป็นกุญแจมาชุดหนึ่ง
แล้วก็เอาอักษรตัวแรกบวกกับเลขในกุญแจอันแรก อักษรตัวที่สองบวกเลขตัวที่สองไปเรื่อยๆ
จนเมื่อชุดตัวเลขในกุญแจที่ใช้หมด ก็กลับไปเริ่มเลขตัวแรกในกุญแจใหม่อีกครั้ง
ง่ายจริงๆ ให้ดินตายเลย (งั้นไปดูคณิตศาสตร์ก่อนที่จะดิ้นตายดีกว่า 555+)

ให้ P = C = Z26 และให้ K = {(a1, a2, a3, ... , ai) ใน Z26 สำหรับ i ใน N}
สำหรับ K = (a1, a2, a3, ... , ai) สร้าง K* = (a1, a2, a3, ... , ai, a1, ...) และกล่าวว่า
eK(x) = (xj + aj) mod 26 และ dK(y) = (yj - aj) mod 26
สำหรับ x, y ที่เป็นสมาชิกของ Z26 และ aj ที่เป็นสมาชิกของ K*

สำหรับนักคณิตศาสตร์แล้ว จะแปลงกุญแจจากสั้นๆ ให้เป็นอนันต์ก่อน แล้วจึงค่อยนำกุญแจไปใช้
จะเห็นว่าวิธีนี้ key space ใหญ่ขึ้นอย่างรวดเร็ว เพียงแค่เพิ่มตัวเลขในกุญแจ ซึ่งคือ 26i นั่นเอง
เลขในกุญแจเพียงแค่ 5 ตัวจะสร้าง key space ที่ใหญ่ถึง 255 = 11.8 x 106 เลยครับ

นอกจากนี้ก็ไม่มีอะไรยากแล้ว ไปเอาโค้ดการเข้ารหัสลับแบบเลื่อนมาแก้ไขนิดเดียวก็ใช้ได้แล้วครับ

บรรทัด 1 เปลี่ยนชื่อ และเปลี่ยนเงื่อนไขการใช้กุญแจจากแบบเลขตัวเดียว เป็นลิสต์เลขหลายตัว
บรรทัด 5 เปลี่ยน logic ของการคำนวน คือให้ใช้เลขในกุญแจตามลำดับที่เปลี่ยนไปเรื่อยๆ

def vigenere(pain_text, key_list):
cipher_text = ""
for i in range(len(pain_text)):
char_num = lower_to_number(pain_text[i])
char_num += key_list[i%len(key_list)]
char_num %= 26
cipher_text += number_to_upper(char_num)
return(cipher_text)


จะเห็นว่า ทางคอมพิวเตอร์นั้น เราไม่จำเป็นต้องสร้าง K* เหมือนทางคณิตศาสตร์ก็ได้
แต่จะใช้ modulo เพื่อวนเรียกใช้เลขที่เราต้องการเมื่อเราใช้เลขในลิสต์หมดครับ
อ๋อ เวลาเรียกฟังก์ชันนี้ขึ้นมาใช้ ตัวแปรด้านหลังต้องพิมพ์เป็นตัวแปรแบบลิสต์อย่างนี้นะครับ

>>> encrypt.vigenere("testvigenerecipher", [4, 25, 7, 12, 0]) 


ส่วนผลลัพท์จะออกมาเป็นอย่างไร ต้องฝากเป็นการบ้านไว้พร้อมกับการเขียน decrypt ครับ
เจอกันคราวหน้าครับ ^__^

Nov 21, 2010

Cryptography ตอนที่ 4 การเข้ารหัสลับแบบสัมพรรค

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

ให้ P = C = Z26 และให้ K = {(a, b) ใน Z26 | gcd(a, 26) = 1}
สำหรับ K = (a, b) จะกล่าวว่า
eK(x) = (ax + b) mod 26 และ dK(y) = a-1(y - b) mod 26 สำหรับ x, y ที่เป็นสมาชิกของ Z26

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

เริ่มจาก K = {(a, b) ใน Z26 | gcd(a, 26) = 1} หมายความว่ากุญแจที่ใช้นี้ ต้องการตัวแปรเพื่อใช้เข้ารหัส 2 ค่า อันนี้ไม่ยากๆ
แต่จะยากตั้งแต่ตรงนี้ไปคือ gcd(a, 26) = 1 หรือห.ร.ม.ของ a กับ 26 ต้องเป็น 1 เท่านั้น
นั่นก็เพราะว่า ถ้าห.ร.ม.ไม่เท่ากับ 1 แล้ว ฟังก์ชัน eK จะไม่เป็น 1-1 ส่งผลให้ไม่สามารถใช้ dK หาข้อความที่ถูกต้องได้
ลองพิจรณาตัวอย่าง สมมติให้ a = 2, b = 0 ข้อความ iamaboy จะแปลงได้เป็น QAYACCW
ซึ่งเห็นได้ว่า b, o ทั้งสองตัวแปลงเป็น C ทำให้แปลง QAYACCW กลับเป็น iamaboy ไม่ได้แล้ว

และเขียนเป็นทฤษฎีบทได้คือ ax = b (mod m) จะมีคำตอบเฉพาะสำหรับ x ที่อยู่ใน Zm เมื่อ b ใน Zm ก็ต่อเมื่อ gcd(a, m) = 1
สำหรับวิธีพิสูจน์จะขอละไว้ก่อน เนื่องจากมันค่อนข้างยาวและใช้ความรู้ด้าน Number theory ที่ผมยังไม่ค่อยถนัดนัก

ขั้นต่อไปที่เราะพิจรณาคือ จะมี a ใดบ้างที่เหลือให้เราใช้ได้
จาก 26 = 2 x 13 ดังนั้นเลขที่ใช้ได้จะไม่มี 2 กับ 13 ประกอบอยู่เมื่อเราแยกตัวประกอบ
ดังนั้น a สำหรับ Z26 คือ 1, 3, 5, 7, 9, 11, 15, 17, 19, 21 และ 25 (ถ้าเปลี่ยน Z26 เป็นอย่างอื่นก็ต้องหากันใหม่)
เห็นได้ว่าวิธีนี้มี a ที่ใช้ได้อยู่ 12 แบบ ส่วน b ยังเหมือนเดิม 26 แบบ ดังนั้น key space มีขนาด 12 x 26 = 312 วิธี (ไม่ปลอดภัย)

สำหรับจำนวนของกุญแจที่เป็นไปได้นี้ ก็มีทฤษฎีบทมารองรับเช่นกัน
ก่อนอื่นเราจะกล่าวว่าเมื่อ a ? 1 และ m ? 2 เป็นจำนวนเต็ม ถ้า gcd(a, m) = 1 เราจะเรียกว่า a และ m เป็นจำนวนเฉพาะสัมพัทธ์
และจำนวนของสมาชิกใน Zm ที่เป็นจำนวนเฉพาะสัมพัทธ์กับ m (ก็คือ a นั่นเอง) จะเรียกว่า ?(m)
ซึ่ง ?(m) จะเท่ากับผลคูณของ (piei - piei-1) ตั้งแต่ i = 1 ถึง n (ไม่พิสูจน์อีกตามเคย ยากส์ส์)

ลองใช้ดีกว่า จากข้างต้น 26 = 21 x 131
ดังนั้น ?(26) = (21 - 20)(131 - 130) = (2-1)(13-1) = 12 ครับ

แต่ปัญหาก็ยังไม่หมดเท่านี้ เพราะแม้เราจะมี a ทั้ง 12 แบบอยู่ในมือแล้ว แต่กลับไปดูด้านบนสุดจะเห็นว่าเราต้องการ a-1
ถ้านี่เป็นการพิจรณาเลขในชีวิตประจำวัน มันก็ไม่น่ามีปัญหา 3-1 ก็คือ 1/3 ไม่เห็นยาก
แต่อย่าลืมว่าตอนนี้เรากำลังพิจรณาเลขใน Z26 ซึ่งเรานิยามแค่การบวกและคูณ ไม่ได้นิยามการหาร
เราจึงต้องใช้สมบัติพื้นฐานที่ว่า aa-1 = a-1a = 1 (mod m)
งานนี้ถึกก่อนได้เปรียบ ลองหาดูเลยว่า a แต่ละตัวที่ได้มานั้น นำไปคูณอะไรแล้ว mod 26 เหลือ 1 (ผลออกมาดังข้างล่างครับ)

1-1 = 1
3-1 = 9
5-1 = 21
7-1 = 15
11-1 = 19
17-1 = 23
25-1 = 25

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

อย่างที่บอกไปแล้วว่า วิธีนี้ดัดแปลงเพิ่มจากการเข้ารหัสลับแบบเลื่อนเพียงนิดส์เดียว
ดังนั้นเราจะเริ่มด้วยการก๊อปปี้โค้ดเก่ามาเปลี่ยนรายละเอียดครับ (ข้อดีของการเขียนโค้ดให้แก้ง่าย)

ที่บรรทัด 1 เปลี่ยนชื่อ และเพิ่มเงื่อนไขของการใช้กุญแจเป็น 2 องค์ประกอบ
ที่บรรทัด 5 เปลี่ยน logic ของการคำนวนให้เข้ากับสมการคณิตศาสตร์ที่พึ่งเรียนไป

def affine(pain_text, a, b):
cipher_text = ""
for i in range(len(pain_text)):
char_num = lower_to_number(pain_text[i])
char_num = a*char_num + b
char_num %= 26
cipher_text += number_to_upper(char_num)
print(cipher_text)


เราก็จะได้โค้ดของการเข้ารหัสลับแบบสัมพรรคมาใช้อย่างถูไถละครับ

ก่อนที่เราจะเขียนโค้ดส่วนนี้ต่อ สังเกตุว่าห.ร.ม.ของ a กับ 26 หรือ gcd(a, 26) = 1
ดังนั้น เราจึงต้องเขียนป้องกันไม่ให้ a ที่รับมามี gcd(a, 26) != 1 ด้วย
วิธีที่จะเขียนตรวจสอบ gcd(a, 26) นั้นก็มีหลายวิธีครับ ตั้งแต่ไล่หาค่าเองด้วยมือตามด้านบนที่ทำมาแล้ว ไปจนถึงการใช้คณิตศาสตร์มาช่วยเลย
สำหรับวิธีที่จะนำเสนอนี้ เป็นการใช้ขั้นตอนวิธีของยูคลิด โดยอยู่ในรูป Recursion ครับ

def gcd(a, b):
if a%b == 0:
return(b)
else:
return(gcd(b, a%b))


เรียบร้อยแล้วก็กลับมาปรับปรุงโค้ดของเราครับ

def affine(pain_text, a, b):
if gcd(26, a) != 1:
return("gcd(26, %(a)i) must be 1") % locals()
else:
cipher_text = ""
for i in range(len(pain_text)):
char_num = lower_to_number(pain_text[i])
char_num = a*char_num + b
char_num %= 26
cipher_text += number_to_upper(char_num)
return(cipher_text)


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

แต่ก่อนอื่น เพื่อให้เรื่องต่างๆ เป็นระเบียบและจัดการง่าย เราจะสร้างไฟล์ใหม่ที่ชื่อว่า cryptologic.py ครับ
และจากตอนที่ผ่านๆ มา จะเห็นว่ามีฟังก์ชันสั้นๆ ที่ไม่ใช่ฟังก์ชันที่เราจะเรียกใช้โดยตรง จะใช้แค่ประกอบในฟังก์ชันหลัก
เช่นพวก lower_to_number(text), ged(a,b) เราย้ายมันมาไว้ที่นี่ครับ
แล้วจึงเพิ่มโค้ดอันแสนสนุกสนานนี้เข้าไปร่วมกับเพื่อนๆ ครับ

def multiple_inv(a, b, s = 0, t = 1):
if a%b == 0:
if b != 1:
return(None) # case of no inverse
else:
return(t)
else:
return(multiple_inv(b, a%b, t, (s-t*int(a/b))%26))


จะเห็นว่า ฟังก์ชันนี้เป็น Recursion อีกแล้ว และที่บรรทัดแรกนั้นมีตัวแปร 4 ตัว คือ a, b, s, t
แต่เวลาจะใช้งานนั้น s เริ่มที่ 0 และ t เริ่มที่ 1 หลังจากนั้นจึงค่อยส่งค่าที่คำนวนกลับเข้าไป
เราจึงสามารถกำหนด s = 0 และ t = 1 ได้ตั้งแต่เริ่มเลย
และยิ่งไปกว่านั้น เวลาเราเรียกใช้ฟังก์ชันครั้งแรก เราสามารถใส่ค่าเพียง a กับ b ก็พอ

อย่าลืมเขียนโค้ด import ที่ไฟล์ encrypt.py เพื่อเรียกใช้งานฟังก์ชันที่อยู่ต่างไฟล์ออกไปนะครับ

from cryptologic import * 


ส่วนการโค้ดรับรหัสลับเพื่อนำมาถอดเป็นข้อความก็จะเป็นดังนี้ครับ (ไฟล์ใหม่ decrypt.py ครับ)

def affine(cipher_text, a, b):
a_inv = multiple_inv(26, a)
if a_inv == None:
return("%(a)i has no inverse") % locals()
else:
pain_text = ""
for i in range(len(cipher_text)):
char_num = upper_to_number(cipher_text[i])
char_num = a_inv*(char_num - b)
char_num %= 26
pain_text += number_to_lower(char_num)
return(pain_text)


เดี๋ยวตอนหน้าจะมันส์กว่านี้อีกครับ ยังไงก็ติดตามกันด้วยนะครับ ^__^

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

Nov 17, 2010

Cryptography ตอนที่ 2 การเข้ารหัสลับแบบเลื่อน

การเข้ารหัสลับแบบแรกที่ง่ายที่สุดนั้น คือการเข้ารหัสแบบ Shift Cipher หรือการเข้ารหัสแบบเลื่อน
วิธีการก็เป็นไปตามชื่อเลย คือทำการเลื่อนตัวอักษรออกไปตามความยาวที่ต้องการ เท่านั้นเองครับ
ชื่อเฉพาะที่น่าสนใจของวิธีนี้คือ Caesar Cipher อันเนื่องมาจากนี่เป็นวิธีที่จูเลียส ซีซาร์ใช้ในการส่งข้อความลับโดยการเลื่อนอักษรออกไป 3 ตำแหน่งนั่นเอง

เราสามารถเขียนการเข้ารหัสแบบเลื่อนเป็นภาษาคณิตศาสตร์ที่รัดกุมได้ ดังนี้

ให้ P = C = K = Z26, สำหรับ 0 ≤ K ≤ 25 จะกล่าวว่า
eK(x) = (x + K) mod 26 และ dK(y) = (y - K) mod 26 สำหรับ x, y ที่เป็นสมาชิกของ Z26

สำหรับบรรทัดแรก จะกล่าวถึงขนาดของ space ข้อมูลที่เราสนใจ ซึ่งในที่นี้ก็คืออักษรภาษาอังกฤษ 26 ตัวตามที่ตกลงกันแต่แรก
ส่วนต่อมาคือการกำหนด key space ที่ถูกนำไปใช้ในบรรทัดต่อไปว่ามีค่าอยู่ในช่วงระหว่าง 0 ถึง 25 นั่นเอง ซึ่งก็คือ 26 แบบนั่นเอง (ไม่ปลอดภัยอย่างแรง!!!)
ตรงนี้ที่ต้องเขียนบอกให้ชัดเจนเพราะเราอาจเขียนมันในกรณีอื่นอีกก็ได้ เช่นสำหรับ K ที่เป็นเลขคู่ให้เลื่อนไปด้านหน้า ส่วน K ที่เป็นเลขคี่ให้เลื่อนไปด้านหลัง เป็นต้นครับ
บรรทัด 2 คือการบอกว่าสำหรับ k ต่างๆ ที่อยู่ใน K นั้นใช้อย่างไร ในที่นี้ก็คือเลื่อนไปด้านหน้าตามขนาดของ K นั่นเองครับ
สังเกตว่าเราใช้ K ตัวใหญ่ใน eKและ dK นั่นก็เพราะว่าเราเขียนระบุในเรื่องของเซตครับ ซึ่งหมายรวมว่าเราสามารถจับ k ใน K ใดๆ ก็ได้มาแทนตรงนั้น

ต่อมาเราจะมาวิเคราะห์อัลกอริทึมกัน โดยทดลงใน Python Shell ตรงๆ
ในเบื้องต้นนั้น เราต้องรับค่าของข้อความที่ต้องการในรูปแบบของ String และกำหนด key ที่เราต้องการให้เลื่อนอักษรไป

>>> pain_text = "testshiftcipher"
>>> k = 3


ต่อมา ให้สร้างตัวแปร String สำหรับเก็บรหัส และใช้ loop วนเข้าไปเพื่อแปลงค่าของตัวอักษรแต่ละตัวๆ ออกมา
เนื่องจากรหัสอักษรในคอมพิวเตอร์นั้นเป็นรหัส ASCII ซึ่งเรียงกันไปตั้งแต่ a = 97 ถึง z = 122 อยู่แล้ว
ในขั้นต้นเพื่อความง่าย เราจะบวกค่าเหล่านี้เข้าไปทันทีด้วยค่า k แล้วแปลงกลับเป็นตัวอักษรเหมือนเดิม

>>> cipher_text = ""
>>> for i in range(len(pain_text)):
... cipher_text += chr(ord(pain_text[i]) + k)
...


เราสามารถเรียก cipher_text ออกมาดูได้ จะเห็นว่าคำที่เราแปลงนั้นกลายเป็น whvwvkliwflskhu (เกือบ) เป็นที่เรียบร้อย
แต่ว่าโค๊ดตรงนี้ยังมีปัญหาอยู่ เพราะว่าถ้าเราใส่อักษรท้ายๆ เข้าไปนั้น เมื่อแปลงเป็นรหัสแล้วก็มีสิทธิ์หลุดออกจากเซตของตัวอักษรอังกฤษไปเป็นอักษรแปลกๆ ได้
เช่นข้อความว่า howareyoutoday เมื่อใช้อัลกอริทึมเก่าจะได้ข้อความ KRZDUH|RXWRGD| จะเห็นว่ามี | ซึ่งไม่ใช่อักษรอังกฤษโผล่เข้ามา
ดังนั้นเราจึงต้องใช้ if เพื่อเช็คว่าค่าที่ได้นั้นเกิน z หรือยัง ถ้าเกินแล้วให้ลบค่าออกด้วย 26
นอกจากนี้ เนื่องจากเราต้องการให้อักษรที่เข้ารหัสแล้วเป็นตัวพิมพ์ใหญ่ด้วย
จาก A = 65 ดังนั้น a - A = 32 เราจึงต้องลบค่าอักษรแต่ละตัวออกไปอีกตัวละ 32 ดังนี้

>>> pain_text = "howareyoutoday"
>>> k = 3
>>> cipher_text = ""
>>> for i in range(len(pain_text)):
... temp = ord(pain_text[i]) + k
... if temp > 122:
... temp -= 26
... temp -= 32
... cipher_text += chr(temp)
...


คราวนี้เมื่อเราใส่ข้อความ howareyoutoday เข้าไป ก็จะได้ผลลัพท์เป็น KRZDUHBRXWRGDB เรียบร้อยแล้วครับ
ต่อไป เราจะสร้างไฟล์ *.py ขึ้นมาเพื่อเก็บฟังก์ชันที่เขียนให้ง่ายต่อการเรียกใช้ในครั้งถัดๆ ไป
โดยคราวนี้เราจะไม่เขียนลวกๆ แล้ว เพราะการเขียนที่เป็นระเบียบจะทำให้ดูแลและพัฒนา code ต่อภายหลังได้ง่ายขึ้น

start_lower = ord('a')
start_upper = ord('A')

def shift(pain_text, key):
cipher_text = ""
for i in range(len(pain_text)):
char_num = lower_to_number(pain_text[i])
char_num += key
char_num %= 26
cipher_text += number_to_upper(char_num)
print(cipher_text)

def lower_to_number(text):
return(ord(text) - start_lower)

def number_to_upper(num):
return(chr(num + start_upper))


จัดการบันทึกไฟล์ที่เขียนนี้ (ในที่นี้ใช้ชื่อ encrypt.py) แล้ว import ไฟล์ผ่าน python shell
เวลาจะเข้ารหัสก็เรียงฟังก์ชันนี้โดยพิมพ์ encrypt.shift("abcdefg", key) เข้าไปเลย
(abcdefg คือคำที่ต้องการให้เข้ารหัส, key คือตัวเลขที่ต้องการให้เลื่อน) แค่นี้ก็เรียบร้อยแล้วครับ ^__^

อ๋อ สำหรับวิธี decrypt นั้น ฝากเป็นการบ้านให้ไปคิดต่อละกันเน้อออ
JRRGOXFN

Nov 16, 2010

Cryptography ตอนที่ 1 ธรรมชาติของการเข้ารหัส (อย่างง่าย)

เมื่อเราลองวิเคราะห์ระบบรหัสลับนั้น เราจะกล่าวได้ว่ามันเป็น (P, C, K, E, D) 5-tuple
เริ่มมาก็งงเลยใช่ปะละ (คนแปลก็งงเหมือนกัน) งั้นเราค่อยๆ ดูกันไปทีละส่วนละกันครับ

tuple คำนี้อาจไม่คุ้นเคยและดูยุ่งยาก แต่ที่จริงแล้วมันเป็นเพียงวิธีการเขียนเรียงลำดับสมาชิกเท่านั้นเอง (ต่างจากเซตที่สมาชิกแต่ละตัวไม่มีความสำคัญในเรื่องลำดับ)
โดยสมาชิกของ tuple นั้นจะต้องมีจำนวนจำกัด n ตัวเสมอ n-tuple ที่เราคุ้นเคยกันดีก็คือ 2-tuple ที่อยู่ในรูป (x, y) หรือเรียกติดปากกันว่าคู่อันดับนั่นเอง
ดังนั้นการที่กล่าวได้ว่าระบบรหัสลับเป็น 5-tuple ก็หมายความว่าระบบนี้มีสิ่งที่สำคัญประกอบอยู่ 5 อย่างนั่นเอง ซึ่งมีความสัมพันธ์กันดังนี้

1. P (Plaintext) คือเซตจำกัดของข้อความอ่านออกที่เป็นไปได้
2. C (Ciphertext) คือเซตจำกัดของข้อความเข้ารหัสที่เป็นไปได้
3. K (Key) คือเซตจำกัดของกุญแจการเข้ารหัสที่เป็นไปได้
4. สำหรับแต่ละ k ที่เป็นสมาชิกของ K (ในทางคณิตศาสตร์ ตัวพิมพ์ใหญ่คือเซต ตัวพิมพ์เล็กคือสมาชิกของเซตนั้นๆ) จะมีวิธีการใช้กุญแจเข้ารหัส (Encryption) eK ที่เป็นสมาชิกของ E และมีวิธีใช้กุญแจถอดรหัส (Decryption) dK ที่เป็นสมาชิกของ D โดยที่ eK : P -> C (eK เป็นฟังก์ชันจาก P ไปยัง C หรือกล่าวง่ายๆ ว่าฟังก์ชัน eK นี้มี P เป็น input ส่วน C เป็น output นั่นเอง) และ dK : C -> P โดยที่ p = dK(eK(p))

จากข้อ 4 นี้ จะหมายความว่า dK เป็นอินเวอร์สของ eK เสมอ และเขียนได้ว่า dK = eK-1
นอกจากนี้ eK และ dK ยังต้องเป็นฟังก์ชันแบบ 1-1 อีกด้วย (จับคู่กันและกันแค่คู่ต่อคู่เท่านั้น) เพราะถ้าไม่เป็นฟังก์ชัน 1-1 แล้ว เมื่อเราต้องการถอดรหัสกลับเป็นข้อความธรรมดา เราอาจไม่รู้เลยว่าคำที่ถูกต้องคืออะไรกันแน่ เพราะ 1 คำอาจถอดรหัสกลับได้หลายแบบนั่นเอง

จากที่เกริ่นมานี้หมายความว่า ถ้าเราสามารถล่วงรู้ eK ได้ เราก็จะหา dK เพื่อถอดรหัสลับได้เช่นกัน
หรือว่าถ้าเราสามารถดักจับข้อความลับ c ได้ และล่วงรู้ข้อความถูกต้อง p บางส่วน เราอาจทดลองหา k ที่ทำให้ c = ek(p) จนสำเร็จ และหา dk ได้ด้วย

Nov 14, 2010

เก็บตกงานโกะวันสุดท้าย

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

เรื่องมันมีอยู่ว่า เราได้รับหน้าที่เป็นกรรมก(า)รในงานแข่ง U-Go ครั้งที่ 15
งานที่ได้รับมอบหมายคือ จัดโต๊ะ ยกของ ไม่ใช้สมอง ใช้แต่แรง อะม่ายช่ายยย
หน้าที่จริงๆ คือ การเป็นผู้ช่วยกรรมการคอยอำนวยความสะดวกแก่การแข่งขัน
ซึ่งได้แก่การปักธงจับคู่ นับหมากเบียวโยมิ และส่งผลคะแนนการแข่งขัน
ส่วนพวกงานใช้แรงนั้น เพราะคนไม่พอเลยต้องลงมือช่วยอย่างเต็มใจ 555+

Nov 13, 2010

Cryptography ตอนที่ 0 เกริ่นนำ

เกริ่นนำ
Cryptography เป็นวิชาที่ว่าด้วยเรื่องของรหัสลับ โดยชื่อนี้มีที่มาจากรากศัพท์จากภาษากรีกว่า kryptos "ลับ" สมาสกับ graph "เขียน" แปลว่าวิธีเขียนความลับนั่นเอง
อีกคำนึงที่มักปรากฎบ่อยๆ ในศาสตร์แห่งการซ่อนเร้นความลับก็คือคำว่า cipher "วิธีเข้ารหัสลับ" ซึ่งเอาไว้บ่งบอกว่าใช้วิธีใดเข้ารหัสลับครับ

ทั้งนี้ทั้งนั้น อย่าสับสนกับ Steganography หรือการอำพรางข้อมูล เพราะแม้ว่าทั้งการเข้ารหัสและการอำพรางข้อมูลนั้นมีจุดมุ่งหมายสูงสุดเดียวกัน (ป้องกันผู้อื่นรับรู้ข้อมูลที่ต้องการปกปิด)
แต่การเข้ารหัสนั้นจะมุ่งเน้นไปที่การปกป้องข้อมูลจากการถูกแกะอ่านได้โดยผู้อื่น ส่วนการอำพรางข้อมูลนั้นมุ่งไปที่การทำให้ผู้อื่นสำคัญผิดว่าไม่มีข้อมูลใดๆ ซ่อนอยู่ในข้อความที่ถ่ายทอดมานั้น


เกี่ยวกับผู้เรียบเรียง
เนื่องจากผมเรียนเอกคณิตศาสตร์ บทเรียนชุดนี้จึงอิงความรู้คณิตศาสตร์บริสุทธิ์ค่อนข้างมาก
บวกกับความชื่นชอบในคอมพิวเตอร์ ก็จะพยายามวิเคราะห์อัลกอริทึมและเขียนโปรแกรมควบคู่กับบทเรียนไปด้วย เพื่อให้สามารถเห็นตัวอย่างได้ชัดเจนยิ่งขึ้น
ส่วนผู้ที่ไม่รู้ทั้งคณิตฯ และคอมฯ ก็ไม่ต้องกังวลไป เพราะผมจะพยายามเขียนให้เข้าใจทั้งคณิตฯ และคอมฯ นั่นแหละ 555+


ข้อตกลง
เพื่อความง่ายในการทำความเข้าใจ รหัสลับทั้งหมดที่ใช้ในบทเรียนจะประกอบด้วยตัวอักษรภาษาอังกฤษเพียง 26 ตัวเท่านั้น ไม่ใช้ตัวเลขหรือเครื่องหมายพิเศษอื่นใดทั้งสิ้น
โดยข้อความที่ถูกต้องนั้นจะเขียนอยู่ในรูปของตัวพิมพ์เล็กทั้งหมด ส่วนข้อความที่ถูกเข้ารหัสแล้วจะเขียนด้วยตัวพิมพ์ให้ญ่ทั้งหมด ดังตัวอย่าง

OHWVVWXGBFUBSWRJUDSKB

คือรหัสลับของคำว่า

letsstudycryptography

และเนื่องจากเราต้องการศึกษาในเชิงคณิตศาสตร์และคอมพิวเตอร์เป็นหลัก การแทนตัวอักษรด้วยตัวเลขจะทำให้ง่ายต่อการนำไปคำนวณในขั้นตอนที่สูงกว่านี้
เราจะให้เลข 0 แทนตัวอักษร a, A เรื่อยไปจนถึงให้ 25 แทน z, Z และเรียกระบบนี้ว่า Z26
ซึ่งหมายถึงเซตของเลขจำนวนเต็มจาก 0 ถึง 25 สำหรับสมาชิกใน Z26 ที่นำมาดำเนินการกันแล้วมีค่าเกิน 25 ก็จะนำไป mod 26 เพื่อให้ผลลัพท์อยู่ใน Z26 เหมือนเดิมครับ

สำหรับการวิเคราะห์อัลกอริทึมและเขียนโปรแกรมนั้น จะใช้ภาษา Python ทั้งหมด เพราะผู้เขียนชอบภาษานี้ครับ ...เอ้ย ไม่ใช่ละ
ที่เลือก Python ก็เนื่องด้วยความง่ายของตัวภาษา สามารถลงมือเขียนได้ทันที ไม่ต้องรู้เชิงลึกเกี่ยวกับคอมพิวเตอร์ก็ได้
หรือถ้าใครเรียนคอมพิวเตอร์มาโดยตรง พอเห็นแล้วจะร้องอ๋อเลย เพราะมีความคล้ายกับ pseudo code เป็นอย่างมาก อ่านแล้วเขียนเป็นภาษาที่ตนเองถนัดได้ทันที
อยากให้ทุกคนที่ต่มอ่านลองเขียนโปรแกรมเล่นกันดูนะครับ ^__^

ความรู้ที่ควรมีประกอบ
Modular arithmetic
Discrete mathematics
Linear algebra
Boolean algebra
Python (programing language)


อ้างอิง
Stinson, D.R., Cryptography: Theory and Practice, Third Edition, 2006
(ในห้องสมุดมีหนังสือให้ยืมมาอ้างอิงแค่เล่มเดียวอยู่ ถ้าหาเพิ่มจะได้ทยอยอัพเดทครับ)

Sep 8, 2010

ไม่คิดว่าจะมีวันนี้

เมื่อหลายปีก่อน ตอนที่ยังอ่านภาษาอังกฤษไม่คล่อง
วันๆ ไม่ยอมไปเรียน เอาแต่เล่นเกม (เดี๋ยวนี้ก้ทำนี่หว่า)
ก็ได้รู้จักเว็บหนึ่งชื่อ EyezMaze เล่นมันทั้งวันจริงๆ
เอาไปเผยแพร่ ก็พากันติดงอมแงมไปหลายราย
ชอบเกมนี้มากๆ จนถึงขั้นเขียนเฉลยเกมออกมาตั้งหลายตอน

แล้วพอไปชวนพี่คนหนึ่งที่เป็นเทพโปรแกรมเมอร์ประจำโรงเรียนเล่น
พี่เค้าก็บอกว่า อ๋อ เคบเล่นแล้วหละ หนุกดี เคยอ่าน blog เค้าด้วย
(ตอนนั้นผมยังไม่รู้เลยว่า blog คืออะไร - -")
แล้วพี่เค้าก็บอกว่า ไอ่คนทำเกม EyezMaze เนี่ย โครตเก่งเลยนะ
ไม่น่าเชื่อว่า งานทั้งหมดนั้นหนะ เป็นงานอดิเรก!
ช๊อกดิ (ลองไปเล่นดู งานเนี้ยบมาก ไม่น่าเชื่อว่าอดิเรกเลย)

ก็ไม่ได้คิดอะไรมากมายหรอกนะ
ไม่ถึงขั้นตั้งเป้าด้วยซ้ำ ว่าซักวันต้องทำให้ได้ขนาดนั้น



แต่ใช้ชีวิตเรื่อยๆ ตามปรกติอยู่ดีๆ ก็เกิดเรื่องที่ไม่คาดฝันขึ้น
คือวันนี้ วันที่คาดคิดไม่ถึงเลยว่าชีวิตนี้จะมีโอกาสได้พานพบ
วันที่เขียนโปรแกรมให้ Lollipop เล่นภาพได้มากกว่า 10 frame
พอเอาไปแจกแล้วมีคนชม แถมชมด้วยคำพูดแบบเดียวกับพี่คนนั้นเลย
ที่ว่า "ไม่น่าเชื่อเลยว่าจะเป็นงานอดิเรก"
แหม ใครๆ ก็รักงานอดิเรกเป็นที่สุดหละนะ
คุณว่ามั้ยครับ ^__^

ตอนนี้กำลังใจมาเต็มเลย อิอิ
ขอบคุณทุกๆ ท่านมากนะครับ

เดินหน้าสู่เป้าหมายต่อไปเต็มกำลัง!

กระทู้ต้นเรื่อง (กลายเป็นกระทู้แนะนำอันดับที่ 1 ของห้องมาบุญครองด้วยแหละ)

Aug 30, 2010

สุโขทัยเมื่อ 2 อาทิตย์ก่อน

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


16 ส.ค. 53
วันเริ่มเรื่อง

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

จนรู้ตัวอีกทีก็เลยไปบ่ายสามแล้ว - -"
ติดเน็ตเกินไปแล้วนะเรานี่ ต้องรีบเลิกซะแล้ว

เข้ามหา'ลัยไปด้วยความหวังว่าจะได้ดูน้องๆ ซ้อมละครกัน
แต่ดันโดนเพื่อนลากไปส่งสถานีขนส่งซะได้
เพื่อนไปแข่งโกะที่สุโขทัย

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

ไอ่เราก็ทนไม่ไหว เห็นสภาพผู้นำที่ขาดไร้ซึ่งการตัดสินใจที่ดีนั้น
เลยออกปากไปว่า ขับรถตามไล่รถเมล์ให้มะ? เดี๋ยวก็ทันที่ลำปาง

ผ่านไปครึ่งชั่วโมง ไม่มีสัญญาณตอบรับจากร่างที่ท่านเรียก
ถึงจะตอบรับมา ก็จะบอกว่า ตามไปถึงลำปางก็ไม่ทันแล้วโว้ย

เลยเซ็งๆ เบื่อๆ จะกลับอยู่ละ
ก็โดนถามมาว่า ให้พันห้า ไปส่ง'โขทัยหน่อยดิ

ไม่อยากตอบรับหรอกนะ อยากให้แก้ปัญหากันเองบ้าง
แต่มันดันติดอยู่ที่ว่า มีลูกทีมเป็นเด็กผู้หญิงต้องไปกับพวกมันด้วยนี่สิ
รถเมล์ไป'โขทัยเที่ยวต่อไปก็ตีสามกว่า
ไม่อยากนึกภาพความวุ่นวายเลยวู้ย

เลยจำใจตกลงไป พามันไปก็ได้
ค่าน้ำมันก็แทบพอดิบพอดี ดีอย่างเดียวอยู่นู่นมีคนเลี้ยงข้าว
จึงขับรถออกจากเชียงใหม่ตอนหกโมงครึ่ง
โชคดีที่ iPod ต่อเข้ารถได้ เลยฟังเพลงกันมันส์เลย ^^

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

ออกร้านสองทุ่มครึ่ง เดินทางไปยังอ.เถิน
แล้วเลี้ยวเข้าทางทุ่งเสลี่ยม ถนนพอใช้แต่โค้งเยอะจริงๆ
สุดท้ายก็ตะลอนๆ มาถึงสุโขทัยตอน 5 ทุ่มจนได้

ดูเบนเล่นโกะกับพี่แหม่ม หลังจากนั้นเราก็เล่นกับเทพ
พี่แหม่มถามว่า กลับกี่โมง (เพราะภารกิจเสร็จเรียบร้อยแล้ว)
เราบอกยังไงก็ได้ พี่แหม่มเลยฝากน้องผู้หญิงคนนั้นกลับด้วย

อาบน้ำเสร็จก็หลับปุ๋ย วันนี้เหนื่อยจริงๆ




17 ส.ค. 53
จบง่ายดาย

ตื่นเช้า 8 โมง เพราะต้องไปส่งเพื่อนที่สนามแข่ง
ไปถึง กรรมการยังไม่มา เลยนั่งเซ็ตเวลานาฬิกาอยู่นิดหน่อย
แล้วก็นั่งจดหมากกระดานกระดานที่แข่งไป 2 กระดาน

ข้าวเที่ยงเป็นอะไรที่แห้งๆ เผ็ดๆ ก็กินข้าวคำน้ำคำตามเคย
กินข้าวไปก็คุยกันไป แอบสงสารน้องผู้หญิงที่โดนต่อว่าว่าเล่นห่วย
กินเสร็จง่วงนอน เลยกลับไปนอนเอาแรงที่โรงแรม

กลับมาอีกทีตอนบ่ายสี่ครึ่ง เค้าแข่งกันเสร็จพอดี
ตอนแรกนึกว่ามื้อเย็นเป็น mk ซะละ ที่ไหนได้ หมูกระทะ 89.-
กินหมูกระทะอร่อยดี (อร่อยเพราะบรรยากาศ?) กินไปเยอะเลย
เสียดายที่ของไม่เยอะเท่าที่เชียงใหม่ แต่ทำไงได้ ถูกกว่าเกือบครึ่ง

ขากลับพี่แอมป์ผู้คร่ำคร่าในวงการโกะขอติดรถกลับลำปางด้วย
ออกสุโขทัยตอนทุ่มครึ่ง เจอฝนตกหนักมากระหว่างทางกลับอีก

คุยกันสนุกดี ถ้ามีโอกาสจะแวะไปกินนอนที่ร้านเกมพี่แอมป์ซัก 2 วัน
แวะไปนั่งรถเพื่อนพี่แอมป์ที่แต่งไว้ดริฟท์ลงดอยสุเทพ (และขอลองขับ)
แวะไปฟังพี่แอมป์โซโลกีตาร์ขั้นเทพที่คอนโดราคาสามแสนกลางเวียง
แวะไปดูเครื่องบดเมล็ดกาแฟที่เป็นโปรเจคจบที่เกือบไม่จบ

ขอบคุณโอกาส ที่ทำให้ผมมีโอกาสได้รู้จักรุ่นพี่เจ๋งๆ เพิ่มอีก 1 คน

ส่งพี่แอมป์ที่ลำปางตอนสี่ทุ่ม (ขับรถได้ช้ามากๆ เพราะฝนตกหนัก)
แล้วก็มุ่งหน้ากลับไปยังเชียงใหม่ย้านเกิด

คุยกันสบายดี ถ้ามีโอกาสจะขอน้องเค้าเป็นไกด์พาเที่ยวเกาหลีซักเดือน
ขอดูหน้าอาจารย์ที่สอนหน่อย อะไรจะโหดปานนั้น ลาแข่งกีฬาก็ไม่ได้
ขอให้น้องเค้าสอนภาษา เพราะเริ่มรู้สึกว่าภาษาเกาหลีมันสนุกจริงๆ
ขอเล่นโกะกับน้องเค้า และสอนน้องเค้าให้เล่นโกะได้เก่งกว่านี้

ขอบคุณความบังเอิญ ที่ทำให้บังเอิญรู้จักรุ่นน้องน่ารักๆ อีก 1 คน

แล้วก็ไปส่งน้องเค้าที่ซอยข้างวัดที่คูเมืองตรงแจ่งหมูกระทะตอนห้าทุ่ม

คุยกับตัวเอง ทบทวนเหตุการณ์ต่างๆ ที่ผ่านมาอย่างไม่คาดฝัน

ขอบคุณความโชคดี ที่แต่งแต้มชีวิตที่มีนี้ด้วยสีสันที่แปลกใหม่

แล้วก็ขับรถกลับถึงบ้านเที่ยงคืน
เป็นวันที่เหนื่อยอีกวัน อาบน้ำนอน




วันนี้ก็เหนื่อยนะ แต่ทำไมยังไม่ง่วงก็ไม่รู้ - -"
นอนไม่หลับโว้ย

Jul 1, 2010

เรื่องสั้นแนวลองทด ความอุดมสมบูรณ์ครั้งที่หนึ่ง

หมายเหตุ: สามารถนำโครงเรื่องไปใช้ต่อได้ตามสะดวกนะครับ

Story:
ปัจจุบันโลกอินเตอร์เน็ตกำลังเติบโตอย่างรวดเร็ว
โลกเทคโนโลยีกำลังก้าวไปอย่างไม่หยุดยั้ง
แต่มนุษย์ก็กำลังขาดแคลนทรัพยากรขึ้นทุกที

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

มนุษย์จะเปลี่ยนไปตลอดกาล
แม้ช่วงแรกเราอาจเป็นเหมือน The Matrix
แต่วิวัฒนาการจะเกิดขึ้นเร็วกว่าที่คิด
เราเปลี่ยนรูปร่างของกายจำลอง
ตัดทอนสิ่งที่ไม่สำคัญออกไป

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

ท้ายสุดนั้น จำนวนมนุษย์จะลดลง
เหลือไม่มาก ไม่น้อยไป
คือหนึ่งเดียวหมายรวมทั้งหมด
และทั้งหมดนั้นแลคือหนึ่งเดียว

My Comment:
1. ถ้าเชื่อในทฤษฎีของฟรอยด์แล้ว บอกได้เลยว่า เขียนเรื่องนี้ด้วยแรงขับทางเพศล้วนๆ 555+
2. ที่เขียนงั้นเพราะเห็นเดี๋ยวนี้มันมั่วเพศกันจังเลย ขนาดแค่ในความคิดก็ไม่เว้น อยากมีคู่ครองเยอะๆ ซะอย่างนั้น - -"
3. แต่จริงๆ แล้ว มันก็เป็นธรรมชาติของสัตว์นี่หน่า มีการต่อสู้แย่งชิงคู่ครองกันเป็นเรื่องปรกติ แถมยังแสดงให้เห็นว่าใครมีมากหมายถึงเก่งอีก
4. เลยคิดว่า จริงๆ แล้วธรรมชาติอาจอยากให้มีการสืบพันธุ์แบบหลายเพื่อหนึ่งได้ แต่วิศวกรรมทางธรรมชาติไม่เอื้ออำนวย เลยยังจำกัดแค่เป็นคู่ๆ เทานั้น
5. เลยลองสร้างสภาพแวดล้อมที่น่าจะเป็นไปได้สำหรับการนี้ดู ...ในโลกที่เราเปลี่ยนไปโดยสิ้นเชิง
6. ตอนจบนี้ยืม Starcraft มาหน่อย เหมือนอย่างที่ Protoss ทำ คือรวมดวงจิตทุกหน่วยเป็นหนึ่งเดียวกัน คือเผ่าพันธุ์แห่ง Protoss ทั้งหมด

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

จำนวนสมบูรณ์คือ จำนวนเต็มที่ผลรวมของตัวหารแท้เท่ากับตัวมันเอง
จึงเห็นได้ว่า ตัวหารแท้ของ 6 คือ 1,2,3 และ 1+2+3 = 6
ดังนั้น 6 จึงเป็นจำนวนสมบูรณ์ครับ ^^