Decode một mật mã nhỏ [1]

Vừa rồi có một người nhờ tôi decode một đoạn code như thế này:

01010100 01101111 01101101 - 01101000 01110101 01101101 - 01100011 01110101 01100001 - 01110010 01101001 01100101 01101110 01100111 - 01100101 01101101.
01000101 01101101 - 01111001 01100101 01110101 - 01100001 01101110 01101000, - 01110110 01100001 - 01100101 01101101 - 01101101 01110101 01101110 01101110 - 01101110 01101111 01101001 - 01100011 01101000 01101111 - 01110100 01100001 01110100 - 01100011 01100001 - 01101101 01101111 01101001 - 01100010 01101001 01100101 01110100. - 01000101 01001101 - 01011001 01000101 01010101 - 01000001 01001110 01001000.

Đoạn code rõ ràng là mã nhị phân, hơn nữa các số lại được nhóm theo từng bộ 8 ký tự rất giống 8 bits của 1 byte. Những ký tự ‘-‘, ‘ ‘, ‘.’, ‘,’ có lẽ là những dấu ngắt từ và ngắt câu bình thường. Quan sát một chút, tất cả các số nhị phân này đều bắt đầu bằng 0 nên tôi mạnh dạn mở ngay calulator (calc) lên chuyển thử mấy số nhị phân đầu tiên ra thập phân. Ah, số thứ 3 và số thứ 6 có cùng giá trị. Tôi copy tất cả dán vào notepad thử tìm xem còn những số nào giống nhau. Có khá nhiều. Vậy rất có thể văn bản được mã hóa theo khóa kiểu Caesar. Nếu đúng vậy thì thật mừng🙂 , vì cùng lắm thì tôi sẽ brute force attack.

Nhưng trước tiên phải chuyển hết văn bản sang số nhị phân đã. Tôi viết một đoạn code nhỏ để làm việc này cho nhanh.

#include
#include
using namespace std;

ifstream fin(“code.txt”);
ofstream fout(“decode.txt”);

int main() {
char ch;
int i,s,p;

while (!fin.eof()) {
fin.get(ch);
if (ch==’0′ || ch==’1′) {
s=0; p=128;
if (ch==’1′) s+=(ch-48)*p;
for (i=0; i < 7; i++) { p/=2; fin.get(ch); if (ch=='1') s+=(ch-48)*p; } fout << s; } else fout << ch; } return 0; }[/sourcecode] Chạy thử, file decode.txt cho ta: [sourcecode language='cpp']84 111 109 - 104 117 109 - 99 117 97 - 114 105 101 110 103 - 101 109. 69 109 - 121 101 117 - 97 110 104, - 118 97 - 101 109 - 109 117 110 110 - 110 111 105 - 99 104 111 - 116 97 116 - 99 97 - 109 111 105 - 98 105 101 116. - 69 77 - 89 69 85 - 65 78 72.[/sourcecode] Hừm, rõ ràng là mã hóa Caesar, những "ký tự" như 109 và 117 lặp lại khá nhiều (đây hẳn là các nguyên âm). Cụm 101 109 lặp lại 2 lần. Nhìn vào cấu trúc mỗi tiếng có không quá 5 ký tự, tôi đoán đây là văn bản Tiếng Việt, có lẽ không dấu. Tuy nhiên đoạn 110 110 - 110 làm tôi khá lúng túng, trong văn bản Tiếng Việt không dấu không thể tìm từ nào 2 ký tự cuối giống nhau cả. Liệu đây có phải đây là văn bản Caesar? Chắn chắn rồi.Nhận thấy số hiệu của các ký tự khá lớn, tôi nghĩ chắc phải (1) chia lấy dư cho 26 (số chữ cái từ A-Z) hoặc (2) lùi tất cả về cùng một lượng nào đó. Cũng có khả năng xấu nhất là (3) phải tìm bảng đối chiếu từng số với mỗi ký tự, công việc này chắc chắn là khó khăn hơn nhiều. (Dù sao thì nhờ vào một bảng phân bố số lượng các chữ cái thì việc này cũng không đến nỗi quá mất thời gian.)

Nguồn: https://i2.wp.com/upload.wikimedia.org/wikipedia/commons/4/41/English-slf.png

Vậy là tôi tiếp tục với đoạn mã C++. Thử (1) chia cho 26 xem sao.
//fout << s; fout << (char) (s%26 + 97); // cộng thêm 97 vì 97 là vị thứ của chữ 'a' trong bảng mã ASCII[/sourcecode] Kết quả: [sourcecode language='cpp'] g h f - a n f - v n t - k b x g z - x f. r f - r x n - t g a, - o t - x f - f n g g - g h b - v a h - m t m - v t - f h b - u b x m. - r z - l r h - n a u.[/sourcecode] Ký tự có vẻ loạn xạ ngầu. Không sao, thử dịch lên và xuống vài đơn vị xem sao. Thay vì xuất ra (char) (s%26 + 97) tôi thử ((s+1)%26 + 97) và ((s-1)%26+97). Vẫn không thành công. Có thể tiếp tục thử thêm nhiều trường hợp những tôi quyết định không làm nữa. Bởi vì cách làm này tương đương như cách sau. Chuyển qua phương án sau. Tôi thấy trong code số 65 là nhỏ nhất, nên quyết định shift tất cả về 65 đơn vị. Thử xem🙂 . [sourcecode language='cpp']//fout << s; //fout << (char) (s%26); fout << (char) (s-65+97); // dịch lui 65 đơn vị, cộng thêm 97 vì 97 là vị thứ của chữ 'a' trong bảng mã ASCII[/sourcecode] Kết quả: [sourcecode language='cpp'] t - ˆ • - ƒ • - ’ ‰ … Ž ‡ - … . e - ™ … • - Ž ˆ, - – - … - • Ž Ž - Ž ‰ - ƒ ˆ - ” ” - ƒ - ‰ - ‚ ‰ … ”. - e m - y e u - a n h.[/sourcecode] Mới đầu thì toàn là ký tự loạn xạ, nhưng thật bất ngờ, đoạn cuối có một văn bản đọc được: "-em - yeu - anh". Vậy là đã có chút manh mối, có thể tiếp tục với cách decode này. Tại sao lại chỉ có 1 phần văn bản được decoded? (còn nữa.)

5 responses to “Decode một mật mã nhỏ [1]

  1. “Tom hum cua rieng em. Em yeu anh, va em munn noi cho tat ca moi biet. EM YEU ANH” —>>> http://www.google.com.vn/search?aq=0&oq=binary+&hl=vi&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=llf&q=binary+translation&btnG=T%C3%ACm+ki%E1%BA%BFm&meta=

    Thực ra đoạn code này rất đơn giản, cậu chỉ cần convert trực tiếp từ binary to text là ok. Nhưng cậu lại quá quan trọng hóa vấn đề khiến cho mọi thứ trở lên rắc rối.

    Thân🙂

  2. Mỗi chữ cái trong máy tính có một mã nhị phân (binary) tương ứng. Chuyển từ mã này về lại chữ cái thì là binary sang text thôi🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s