IV. Giới thiệu một số mật mã cổ điển
1. Mật mã Caesar
Mật mã Caesar là một trong những mật mã cổ điển xuất hiện sớm nhất, được đặt tên theo nhà văn và nhà sử học người La Mã Julius_Caesar - người đã sử dụng nó trong các thư từ bí mật của mình. Mã hóa Caesar còn được biết đến với tên mật mã chuyển vị, biểu thị cho phương thức mã hóa dịch chuyển vị trí chữ cái.
Mật mã Caesar điển hình và thường thấy nhất sử dụng phép dịch chuyển ký tự sang phải đơn vị. Số vị trí dịch chuyển này có thể được coi là giá trị của secret ket . Đối với bảng chữ cái tiếng anh in hoa , mã hóa Caesar đang xét có thể hiểu là thay thế các chữ cái bằng chữ cái đứng liền sau nó vị trí, chẳng hạn , , đối với các chữ cái cuối cùng sẽ được thay thế lần lượt bởi .
Bởi tính dịch chuyển vòng quanh, chúng ta còn có thể biểu thị cách mã hóa của mật mã Caesar dưới dạng module trong toán học:
Trong đó là hàm mã hóa, là hàm giải hóa, là giá trị secret key.
Ví dụ, đối với bản mã VIBLOSECURITY
có:
Với phạm vi chữ cái in hoa trong bảng chữ cái, để thực hiện mã hóa Caesar trong lập trình, có thể xét hai trường hợp về ký tự cần mã hóa, sử dụng bảng mã ASCII, ví dụ đối với trường hợp :
k = 3
for i in plaintext: if (i < 'X'): print(chr(ord(i) + k), end = "") else: print(chr(ord(i) + k - 26), end = "")
Sử dụng module, chúng ta có chương trình mã hóa tổng quát Caesar như sau:
for i in plaintext: print(chr(((ord(i) - 65 + k) % 26) + 65), end = "")
Sử dụng hàm String find(), chúng ta có chương trình rút gọn như sau:
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' for i in plaintext: print(alphabet[(alphabet.find(i) - 3) % 26], end = '')
Bài tập dành cho bạn đọc: hãy viết lại hàm giải mã Caesar dựa trên các chương trình trên.
Challenge CTF: King Ceaser Cipher
Văn bản mã hóa từ đề bài: a22W362Z273a40Z22X56357W5268a411
với key có giá trị .
Quan sát ciphertext nhận thấy các ký tự đã mã hóa có thể là chữ cái in hoa, in thường hoặc chữ số, kết hợp với gợi ý:
King Ceasar II's cipher uses 2 alphabet: 1 has 52 characters and 1 has 10 characters.
Chúng ta có thể dự đoán hai chuỗi alphabet được tác giả sử dụng để mã hóa theo mật mã Caesar lần lượt là:
alpha1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
alpha2 = '0123456789'
Thông tin về số vị trí dịch chuyển key = 48
áp dụng đối với mỗi dãy alphabet theo tính chất module có thể suy ra quá trình mã hóa:
- Nếu ký tự nằm trong dãy thứ nhất sẽ dịch chuyển vòng quanh sang phải vị trí, hay . Khi giải mã ta có:
- Tương tự, nếu ký tự thuộc dãy thứ hai sẽ có: , giải mã:
Từ hướng giải trên, chúng ta có chương trình tham khảo như sau:
ciphertext = 'a22W362Z273a40Z22X56357W5268a411'
key = 48
flag = '' alpha1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
alpha2 = '0123456789' for i in ciphertext: if i in alpha1: flag += alpha1[(alpha1.find(i) + 4) % 52] else: flag += alpha2[(alpha2.find(i) + 2) % 10] print('Flag{%s}' % flag)
2. Mật mã Morse
Mã Morse được đặt theo tên của Samuel Morse - nhà phát minh của điện báo, mật mã thường được sử dụng trong các lĩnh vực viễn thông, quân đội và hàng không. Mã Morse mã hóa văn bản dưới dạng các chuỗi xung điện "ngắn" và "dài", đại diện bởi hai ký tự .
và -
(dots and dash).
Thông thường, chúng ta ký hiệu dấu khoảng cách bằng ký tự /
trong Morse. Ví dụ mã hóa viblo security
trong mật mã Morse thu được:
...- .. -... .-.. --- / ... . -.-. ..- .-. .. - -.--
Đối với xây dựng chương trình mã hóa và giải mã mật mã Morse trong Python, chúng ta cần khai báo một dict chứa từng cặp giá trị ký tự và mã hóa của nó.
MORSE_CODE_DICT = {'A':'.-', 'B':'-...','C':'-.-.', 'D':'-..', 'E':'.', 'F':'..-.', 'G':'--.', 'H':'....', 'I':'..', 'J':'.---', 'K':'-.-', 'L':'.-..', 'M':'--', 'N':'-.', 'O':'---', 'P':'.--.', 'Q':'--.-', 'R':'.-.', 'S':'...', 'T':'-', 'U':'..-', 'V':'...-', 'W':'.--', 'X':'-..-', 'Y':'-.--', 'Z':'--..', '1':'.----', '2':'..---', '3':'...--', '4':'....-', '5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.', '0':'-----', ', ':'--..--', '.':'.-.-.-', '?':'..--..', '/':'-..-.', '-':'-....-', '(':'-.--.', ')':'-.--.-'}
Từ đó dựa vào ánh xạ trên để mã hóa và giải mã văn bản. Bạn đọc có thể tham khảo thêm tại https://www.geeksforgeeks.org/morse-code-translator-python/.
Challenge Mã Morse Kì Lạ
Dễ dàng nhận thấy đề bài thực hiện mã hóa flag theo định dạng mã Morse, thay dots và dash thành hai ký tự X và Y.
YYXY YXYY YX XXY { X YYYY Y _ XX XXX YXY YYY Y _ XYXX XXX YYX _ XYX XY XXX YXX _ X YYYY Y _ XX XXX YXY Y _ XYXX XXX YYX _ XYX XY XXX YXX }
Để xác định được thứ tự X và Y tương ứng với dots hay dash, chúng ta lưu ý định dạng của flag là Flag{...}. Suy ra F được mã hóa thành YYXY
, mà F trong mật mã Morse là ..-.
nên có X = -
, Y = .
. Hay chúng ta có flag chuyển sang dạng Morse "chuẩn hơn":
ciphertext = 'YYXY YXYY YX XXY { X YYYY Y _ XX XXX YXY YYY Y _ XYXX XXX YYX _ XYX XY XXX YXX _ X YYYY Y _ XX XXX YXY Y _ XYXX XXX YYX _ XYX XY XXX YXX }' flag = '' for i in ciphertext: if i == 'Y': flag += '.' elif i == 'X': flag += '-' else: flag += i print(flag)
Kết quả:
..-. .-.. .- --. { - .... . _ -- --- .-. ... . _ -.-- --- ..- _ -.- -. --- .-- _ - .... . _ -- --- .-. . _ -.-- --- ..- _ -.- -. --- .-- }
Từ đây chúng ta có thể dựa vào bảng mã Morse tìm ra flag hoặc sử dụng một số trang web decode online (chẳng hạn https://morsedecoder.com/):
Bạn đọc có thể thử sức với challenge morse-code trên nền tảng Pico CTF, với mật mã Morse được cho dưới dạng file .wav rất thú vị.
3. Mật mã Vigenère
Mật mã Vigenère được đặt tên theo nhà mật mã học người Pháp Blaise de Vigenère (1523-1596). Mã hóa Vigenère có thể coi là một sự mở rộng của mật mã Caesar bởi nó là sự kết hợp xen kẽ nhiều bước mã hóa Caesar với các khóa dịch chuyển khác nhau.
Mật mã Vigenère sử dụng một bảng vuông được tạo thành bởi bảng mã Caesar, mỗi hàng có thứ tự các chữ cái lệch sang bên trái một vị trí so với hàng trên.
Để mã hóa, mật mã Vigenère sử dụng một từ khóa lặp lại nhiều lần liên tiếp cho tới khi độ dài bằng thông điệp mã hóa. Ví dụ, với thông điệp VIBLOSECURITY và từ khóa TIME, thực hiện lặp thu được: TIMETIMETIMET (độ dài ). Như vậy mỗi ký tự của plaintext tương ứng với một key trong từ khóa.
Plaintext | V | I | B | L | O | S | E | C | U | R | I | T | Y |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
The key | T | I | M | E | T | I | M | E | T | I | M | E | T |
Quá trình mã hóa thực hiện tìm kiếm lần lượt ký tự ở hàng và cột với là cặp ký tự của plaintext và key tương ứng (Không quan trọng thứ tự bởi bảng mã Vigenère đối xứng về hàng và cột). Ví dụ, mã hóa ký tự V trên chúng ta tìm kiếm ký tự hàng V cột T được ký tự O, mã hóa ký tự tiếp theo thu được Q, tiếp tục quá trình thu được ciphertext cuối cùng: OQNPHAQGNZUXR.
Việc giải mã ngược lại chúng ta sẽ tìm trên hàng của key thứ tự cột của ký tự mã hóa (hoặc tìm trên cột của key thứ tự hàng của ký tự mã hóa). Ví dụ: Hàng T, ký tự O thuộc cột V (ký tự plaintext); hàng I, ký tự Q thuộc cột I (ký tự plaintext); ...
Tổng quát, biểu diễn quá trình mã hóa và giải mã Vigenère qua công thức module như sau:
Trong đó, và lần lượt là hàm mã hóa và giải mã, và chỉ thứ tự thứ của plaintext và từ khóa.
Thực hiện trong chương trình Python, trước hết chúng ta cần có hàm sinh key cho cùng độ dài với plaintext:
def generateKey(string, key): key = list(key) if len(string) == len(key): return(key) else: for i in range(len(string) - len(key)): key.append(key[i % len(key)]) return("" . join(key))
Thực hiện mã hóa, ý tưởng tương tự má hóa Caesar:
def cipherText(string, key): cipher_text = [] for i in range(len(string)): x = (ord(string[i]) + ord(key[i])) % 26 x += ord('A') cipher_text.append(chr(x)) return("" . join(cipher_text))
Hàm giải mã:
def originalText(cipher_text, key): orig_text = [] for i in range(len(cipher_text)): x = (ord(cipher_text[i]) - ord(key[i]) + 26) % 26 x += ord('A') orig_text.append(chr(x)) return("" . join(orig_text))
Bài tập dành cho bạn đọc, hãy hoàn thành challenge CTF Vigenere.