+2

General knowledge in Cryptography - kiến thức tổng quan trong mật mã học (phần 1)

I. Mở đầu về chuỗi bài viết Cryptography

1. Lịch sử hình thành

Mật mã học (Cryptography) là một lĩnh vực nghiên cứu khoa học đóng vai trò quan trọng và hấp dẫn trong ngành khoa học máy tính (Computer Science) và an toàn thông tin (Infomation Security).

Các vấn đề liên quan đến mật mã đã xuất hiện từ hàng ngàn, chục ngàn năm trước, trước khi khái niệm của nó được định nghĩa. Sự hiện hữu đầu tiên của mật mã học được thể hiện dưới nhu cầu giao tiếp và chia sẻ thông tin của con người thời cổ đại: Các ký hiệu tượng trưng cho sự vật, sự việc, ... có thể coi là một dạng mã hóa, và chỉ những người sử dụng, được tiếp cận chúng mới có thể giải mã và hiểu được ý nghĩa.

image.png (Chữ viết tượng hình của Hy Lạp cổ đại là một dạng mã hóa thông tin)

Thuật ngữ Cryptography có nguồn gốc từ tiếng Hy Lạp, được tạo ra bằng cách kết hợp hai từ kryptós (ẩn) và gráphein (viết ra). Theo thời gian, mật mã học ngày càng đóng vai trò quan trọng trong cuộc sống và xã hội loài người: Từ tác dụng trao đổi thông tin thường ngày cho tới các kỹ thuật mã hóa thông điệp, thư mật, đến những hệ thống bảo mật phức tạp, mang tính lịch sử trong chiến tranh, và cho tới ngày nay, đã phát triển thành một bộ môn khoa học nghiên cứu nhằm đảm bảo an toàn, bảo mật trong quá trình truyền tải thông tin.

image.png (Máy Enigma, được người Đức sử dụng trong Đại chiến thế giới II)

2. Tổng quan chuỗi bài viết Cryptography - Mật mã học

Trong chuỗi bài viết Cryptography - Mật mã học, chúng ta sẽ cùng tìm hiểu về các loại mật mã cổ điển cho tới hiện đại, phân tích các kỹ thuật mã hóa chuyên sâu, tìm hiểu các phương pháp tấn công, và khám phá các ứng dụng thực tế của mật mã học trong đời sống hàng ngày cũng như lĩnh vực công nghiệp. Từ đó hiểu được nguyên lý hoạt động, bản chất của các kỹ thuật mã hóa, giải mã, hướng tới xây dựng và phát triển chuyên sâu trong bộ môn khoa học này.

Với công nghệ hiện tại, quá trình mã hóa và giải mã sẽ được thực hiện dưới dạng lập trình. Với các bạn bắt đầu tiếp xúc tới bộ môn này thường thắc mắc nên sử dụng loại ngôn ngữ lập trình nào. Xuyên suốt trong chuỗi bài viết, chúng ta sẽ sử dụng Python (Phiên bản mới nhất hiện tại là 3.11) để xây dựng các chương trình. Đây cũng là ngôn ngữ được ưa chuộng nhất trong giới mật mã bởi tính đơn giản, dễ lập trình, dễ đọc hiểu và có khối lượng thư viện hỗ trợ phong phú, đa dạng (Tất nhiên không phải là bắt buộc).

II. Một số kỹ thuật mã hóa cơ bản

Nhìn vào bộ môn toán học hiện nay, những công thức phức tạp về tích phân, nguyên hàm chắc hẳn đã làm cho nhiều bạn trong số chúng ta từng một thời "đau đầu". Đứng ở góc nhìn hiện tại trở về thuở sơ khai của môn toán, toán học chỉ đơn giản là những con số cực kỳ đơn giản, cùng với hai phép tính "cộng", "trừ" cơ bản. Có thể thấy, mọi kiến thức chuyên sâu, phức luôn bắt đầu từ những yếu tố cơ bản nhất. Đối với lĩnh vực mật mã học cũng vậy, chúng ta cần nắm chắc các kỹ thuật mã hóa cơ bản, sơ khai nhất.

1. Bảng mã ASCII

ASCII (American Standard Code for Information Interchange) sử dụng 77 bit nhị phân để mã hóa các ký tự dựa trên bảng chữ cái La Tinh (Các máy tính hiện nay sử dụng 88 bit, bit thứ tám gọi là bit parity dùng để kiểm tra lỗi).

Trong bảng mã ASCII chuẩn có 128128 ký tự, trong đó: 9595 ký tự in ra được, được đánh số từ 3232 đến 126126, còn lại là các ký tự đặc biệt cùng với lệnh thực hiện. Với bảng mở rộng hiện nay đã bổ sung thêm và bao gồm 256256 ký tự.

image.png

Chúng ta có thể mã hóa các ký tự bằng bảng ASCII trở thành các số nguyên trong hệ thập phân. Ví dụ, sử dụng bảng trên chúng ta có thể mã hóa từ Viblo thành:

86 105 98 108 111

Đối với Python, chúng ta có thể sử dụng hàm ord() mã hóa từng ký tự sang mã ASCII dạng thập phân, hàm chr() thực hiện giải mã ngược lại.

image.png

2. Hexadecimal - Hệ thập lục phân

Với con người, hệ thập phân đã trở nên quen thuộc và rất dễ tiếp cận. Đó là bởi vì từ xa xưa, con người đã sử dụng 1010 ngón tay để đếm số lượng thức ăn. Chúng ta cũng đã vô cùng quen thuộc với 1010 chữ số từ 00 đến 99. Đối với máy tính, do chỉ có thể biểu diễn được hai trạng thái duy nhất (on - off) nên con người đã phát minh ra hệ nhị phân để máy tính có thể "hiểu". Vậy thì, vì sao lại tồn tại hệ thập lục phân, nó có gì đặc biệt?

Hexadecimal - Hệ thập lục phân được công ty IBM giới thiệu với thế giới điện toán năm 19631963. Tên gọi là sự kết hợp từ chữ hexi (tiếng Hy Lạp có nghĩa là sáu) và decimal (tiếng Latin có nghĩa là mười) được biểu diễn bằng 1616 ký tự gồm 1010 ký tự số từ 00 đến 9966 ký tự chữ từ AA đến FF.

image.png

Hexadecimal giúp biểu diễn hệ nhị phân một cách ngắn gọn và trực quan hơn, giúp giảm tải lượng tài nguyên cần sử dụng khi cần biểu diễn các dữ liệu lớn. Việc chuyển đổi giữa Binary và Hexadecimal cũng vô cùng đơn giản. Ví dụ, để biểu diễn số nhị phân 10010110101001011010 sang hệ thập phân, thực hiện các bước:

  • Bước 11: Bổ sung thêm các chữ số 00 vào đầu để tổng số chữ số là bội của 44. Thu được 001001011010001001011010.
  • Bước 22: Chia thành từng nhóm 44 chữ số, thu được 0010 0101 10100010\ 0101\ 1010
  • Bước 33: Biểu diễn từng nhóm chữ số sang hệ 1616, cuối cùng ghép lại thu được kết quả ở hệ Hexadecimal: 25A.

Thực hiện đảo ngược các bước trên để chuyển đổi ngược lại từ hệ 1616 sang hệ cơ số 22.

Trong Python, chúng ta có thể sử dụng hàm hex() để chuyển đổi các số sang hệ Hexadecimal. Giá trị đầu vào có thể là một số ở hệ cơ số bất kỳ, kết quả trả về ở dạng thập lục phân với ký tự thường và tiền tố 0x. Ví dụ:

# decimal
print(hex(250))  # output: 0xfa
# binary
print(hex(0b1011))  # output: 0xb
# octal
print(hex(0o54))  # output: 0x2c
# hexadecimal
print(hex(0X4AF))  # output: 0x4af

Chúng ta cũng có thể sử dụng .hex() để chuyển một chuỗi sang biểu diễn dạng hex, nhưng trước hết cần chuyển chuỗi đó sang dạng byte (có thể sử dụng hàm encode()). Ví dụ:

str = "Hexadecimal_is_very_useful"
str_in_byte = str.encode()  # b'Hexadecimal_is_very_useful'
str_in_hex = str_in_byte.hex()
print(str_in_hex)

image.png

Ngược lại, khi được cung cấp một chuỗi hex, chúng ta có thể chuyển chuỗi đó sang dạng byte bằng bytes.fromhex(). Ví dụ:

str_in_hex = '48657861646563696d616c5f69735f766572795f75736566756c'
str_in_byte = bytes.fromhex(str_in_hex)

print(str_in_byte)

image.png

Một thử thách nhỏ dành cho bạn đọc: Bạn có thể chuyển chuỗi sau về dạng plain text không?

333333373333333633333336333333393333333633333332333333363336333333333336333633363333333733363332333333373333333733333336333333353333333633363333333333363333333333333336333633363333333633363334333333363333333533333335333633363333333733333334333333363336333633333335333633363333333633333333333333373333333233333337333333393333333733333330333333373333333433333336333633363333333633333337333333373333333233333336333333313333333733333330333333363333333833333337333333393333333733363334

Tài liệu tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí