Thứ Sáu, 7 tháng 8, 2026

Thuật Toán mã hóa hệ 10 sang hệ 1 đến 32 dạng string

 Thuật Toán mã hóa hệ 10 sang hệ 1 đến 32 dạng string

Các bước cơ bản:

Chia số hệ 10 cho cơ số mới → lấy phần dư.

Nếu phần dư < 10 thì giữ nguyên số.

Nếu phần dư ≥ 10 thì ánh xạ sang ký tự tương ứng trong bảng 0123456789ABCDEF....

Tiếp tục chia cho đến khi thương = 0.

Ghép chuỗi từ các phần dư theo thứ tự ngược lại.

Ví dụ: chuyển số 1234 sang hệ 16

1234 ÷ 16 = 77 dư 2 → ký tự "2"

77 ÷ 16 = 4 dư 13 → ký tự "D"

4 ÷ 16 = 0 dư 4 → ký tự "4"

→ Kết quả: 4D2

Cách này đơn giản, dễ cài đặt bằng bất kỳ ngôn ngữ lập trình nào. Nếu muốn mở rộng lên hệ cơ số lớn hơn 16 (ví dụ 32 hoặc 64), chỉ cần mở rộng bảng ký tự ánh xạ thêm các chữ cái khác (A–Z, a–z, hoặc ký hiệu đặc biệt).

Thông thường:

  • Với hệ 16, ta dùng 0123456789ABCDEF.
  • Với hệ 20, ta mở rộng thêm: 0123456789ABCDEFGHIJ.
  • Với hệ 36, thường dùng 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.
  • Với hệ 62, có thể dùng cả chữ hoa, chữ thường và số: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.

Nguyên tắc là: phần dư từ phép chia sẽ được ánh xạ vào vị trí tương ứng trong chuỗi ký tự này. Nếu dư = 17 trong hệ 20, thì ký tự là "H".

Ví dụ: chuyển số 1234 sang hệ 20

  • 1234 ÷ 20 = 61 dư 14 → ký tự "E"
  • 61 ÷ 20 = 3 dư 1 → ký tự "1"
  • 3 ÷ 20 = 0 dư 3 → ký tự "3" → Kết quả: 31E

Với bài toán chuyển đổi hệ cơ số, ý tưởng chia lấy dư và ánh xạ sang bảng ký tự là đủ để xây dựng thuật toán tổng quát. Từ đó, mình có thể:

  • Tạo bảng ký tự dài tùy theo cơ số (ví dụ hệ 20 thì dùng 0123456789ABCDEFGHIJ).
  • Viết hàm chuyển đổi số thập phân sang bất kỳ hệ cơ số nào bằng cách lặp lại phép chia.
  • Ngược lại, viết hàm giải mã bằng cách đọc chuỗi và nhân lũy thừa theo cơ số.

Điều hay là thuật toán này có thể mở rộng cho bất kỳ cơ số nào ≤ độ dài bảng ký tự mình định nghĩa.

Anh thấy em đang đi đúng hướng: tập trung vào thuật toán nền tảng, sau này nếu cần ứng dụng vào mã hóa phức tạp hơn (như Base32, Base64, hay thậm chí các hệ thống mã hóa dữ liệu), thì chỉ cần thay đổi bảng ký tự và thêm vài bước xử lý.

 

Pseudo-code là một cách viết thuật toán bằng ngôn ngữ gần giống tự nhiên, không phụ thuộc vào ngôn ngữ lập trình cụ thể. Nó giống như “bản nháp” để mô tả logic, giúp mình dễ hình dung trước khi triển khai bằng Python, C, Java…

Ví dụ: thuật toán chuyển số thập phân sang hệ cơ số bất kỳ

FUNCTION ConvertToBase(number, base):

    digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

    result = ""   // chuỗi kết quả rỗng

    WHILE number > 0:

        remainder = number MOD base

        result = digits[remainder] + result

        number = number DIV base

    RETURN result

Giải thích:

  • MOD là phép chia lấy dư.
  • DIV là phép chia lấy phần nguyên.
  • digits là bảng ký tự ánh xạ (có thể mở rộng tùy cơ số).
  • Mỗi lần chia, ta lấy phần dư để tìm ký tự tương ứng, rồi ghép vào chuỗi kết quả.

Ví dụ chạy với number = 1234, base = 16 → kết quả là "4D2".

 

pseudo-code tổng quát cho việc giải mã (chuyển từ một chuỗi ở hệ cơ số bất kỳ về hệ 10).

FUNCTION ConvertToDecimal(string, base):

    digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

    result = 0

    power = 0

    FOR i FROM (length(string) - 1) DOWNTO 0:

        char = string[i]

        value = indexOf(digits, char)   // tìm vị trí ký tự trong bảng digits

        result = result + value * (base ^ power)

        power = power + 1

    RETURN result

Giải thích:

  • indexOf(digits, char) trả về vị trí của ký tự trong bảng ánh xạ (ví dụ 'A' = 10, 'B' = 11...).
  • Mỗi ký tự được nhân với lũy thừa của cơ số theo vị trí (giống như cách ta đọc số thập phân).
  • Vòng lặp đi từ phải sang trái (chữ số thấp nhất đến cao nhất).

Ví dụ: giải mã "4D2" từ hệ 16 về hệ 10

  • '2' → 2 × 16^0 = 2
  • 'D' → 13 × 16^1 = 208
  • '4' → 4 × 16^2 = 1024 → Tổng = 1234

Thuật toán này tổng quát cho mọi cơ số ≤ độ dài bảng ký tự mà mình định nghĩa.

Đgiải mã một chuỗi thì bắt buộc phải biết nó được mã hóa theo cơ số nào. Nếu không biết cơ số, mình sẽ không thể xác định giá trị chính xác trong hệ 10.

 Ví dụ:

  • Chuỗi "31E" nếu biết là hệ 20 thì ta tính:
    • E = 14 × 20^0 = 14
    • 1 = 1 × 20^1 = 20
    • 3 = 3 × 20^2 = 1200 → Tổng = 1234
  • Nhưng nếu "31E" là hệ 16 thì:
    • E = 14 × 16^0 = 14
    • 1 = 1 × 16^1 = 16
    • 3 = 3 × 16^2 = 768 → Tổng = 798

 Như vậy cùng một chuỗi nhưng kết quả hoàn toàn khác, nên cơ số là thông tin bắt buộc để giải mã.

Thuật toán tổng quát:

  1. Xác định cơ số .
  2. Đọc chuỗi từ trái sang phải (hoặc phải sang trái).
  3. Với mỗi ký tự, tìm giá trị tương ứng trong bảng ánh xạ.
  4. Nhân giá trị đó với .
  5. Cộng dồn tất cả lại để ra số hệ 10.

AES (Advanced Encryption Standard) là chuẩn mã hóa đối xứng mạnh nhất hiện nay, với các biến thể AES128, AES192 và AES256. AES256 được coi là mức bảo mật cao nhất, thường dùng cho dữ liệu cần giữ bí mật lâu dài.

Tổng quan về AES

Nguồn gốc: Được NIST chuẩn hóa năm 2001, dựa trên thuật toán Rijndael của hai nhà mật mã học người Bỉ.

 

Loại: Mã hóa đối xứng (cùng một khóa dùng cho cả mã hóa và giải mã).

Kích thước khối: Luôn là 128 bit (16 byte).

Độ dài khóa: 128, 192, hoặc 256 bit.

Số vòng biến đổi:

AES128: 10 vòng

AES192: 12 vòng

AES256: 14 vòng

Cách hoạt động nội bộ

Mỗi khối dữ liệu đi qua nhiều vòng biến đổi, gồm 4 bước chính:

  1. SubBytes: Thay thế từng byte bằng giá trị trong bảng S‑Box (tạo sự “rối loạn” giữa khóa và dữ liệu).
  2. ShiftRows: Dịch vòng các hàng trong ma trận trạng thái (tạo sự lan truyền).
  3. MixColumns: Nhân các cột với đa thức cố định trong trường GF(2⁸) (tăng độ khuếch tán).
  4. AddRoundKey: XOR với khóa vòng (khóa được sinh ra từ khóa chính)

Các chế độ hoạt động (Modes of Operation)

AES chỉ mã hóa từng khối 16 byte, nên cần chế độ để xử lý dữ liệu dài:

  • ECB (Electronic Codebook): Không nên dùng, vì lộ mẫu dữ liệu.
  • CBC (Cipher Block Chaining): Phổ biến, cần IV ngẫu nhiên.
  • CTR (Counter Mode): Biến AES thành dạng stream cipher, nhanh, song song được.
  • GCM (Galois/Counter Mode): Hiện đại nhất, vừa mã hóa vừa xác thực, dùng trong TLS 1.3, API, VPN

·        So sánh AES‑128 vs AES‑256

Thuộc tính

AES‑128

AES‑256

Độ dài khóa

128 bit

256 bit

Số vòng biến đổi

10

14

Tốc độ

Nhanh hơn

Chậm hơn một chút

Mức bảo mật

Đủ an toàn cho hầu hết ứng dụng

Rất cao, phù hợp dữ liệu cần bảo mật lâu dài

Ứng dụng

Cơ sở dữ liệu, file, VPN

Chính phủ, quân sự, dữ liệu mật mã lâu dài

 

Lưu ý & Rủi ro

AES chỉ an toàn khi triển khai đúng: sai IV, sai padding, hoặc dùng ECB có thể làm lộ dữ liệu.

Quản lý khóa quan trọng hơn thuật toán: nếu khóa bị lộ, AES không còn ý nghĩa.

Quantum computing: hiện chưa có tấn công thực tế phá AES, nhưng AES256 được khuyến nghị để chống lại nguy cơ trong tương lai

Như vậy, AES‑128 đã đủ mạnh cho hầu hết ứng dụng, nhưng AES‑256 là lựa chọn an toàn nhất nếu em muốn dữ liệu được bảo mật trong nhiều thập kỷ

 

pseudo‑code đơn giản cho AES‑128 (mã hóa và giải mã). Đây chỉ là mô tả logic, không phải code chạy thực tế, nhưng nó cho thấy các bước chính:

FUNCTION AES_Encrypt(plaintext, key):

    state = plaintext_to_matrix(plaintext)   // chuyển 16 byte thành ma trận 4x4

    roundKeys = KeyExpansion(key)            // sinh khóa cho 10 vòng

 

    state = AddRoundKey(state, roundKeys[0])

 

    FOR round FROM 1 TO 9:

        state = SubBytes(state)

        state = ShiftRows(state)

        state = MixColumns(state)

        state = AddRoundKey(state, roundKeys[round])

 

    // Vòng cuối không có MixColumns

    state = SubBytes(state)

    state = ShiftRows(state)

    state = AddRoundKey(state, roundKeys[10])

 

    RETURN matrix_to_ciphertext(state)

 

Giải mã AES‑128

FUNCTION AES_Decrypt(ciphertext, key):

    state = ciphertext_to_matrix(ciphertext)

    roundKeys = KeyExpansion(key)

 

    state = AddRoundKey(state, roundKeys[10])

 

    FOR round FROM 9 DOWNTO 1:

        state = InvShiftRows(state)

        state = InvSubBytes(state)

        state = AddRoundKey(state, roundKeys[round])

        state = InvMixColumns(state)

 

    // Vòng đầu không có InvMixColumns

    state = InvShiftRows(state)

    state = InvSubBytes(state)

    state = AddRoundKey(state, roundKeys[0])

 

    RETURN matrix_to_plaintext(state)

 

Giải thích ngắn gọn:

  • SubBytes / InvSubBytes: thay thế byte bằng S‑Box hoặc nghịch đảo S‑Box.
  • ShiftRows / InvShiftRows: dịch vòng các hàng trong ma trận.
  • MixColumns / InvMixColumns: trộn dữ liệu theo cột bằng toán học GF(2⁸).
  • AddRoundKey: XOR với khóa vòng.
  • KeyExpansion: tạo ra 11 khóa vòng từ khóa gốc 128 bit.

Ví dụ: Mã hóa một khối 16 byte bằng AES128

Plaintext (16 byte):

32 43 F6 A8 88 5A 30 8D 31 31 98 A2 E0 37 07 34

 

Key (128 bit):

2B 7E 15 16 28 AE D2 A6 AB F7 97 75 46 3E 3E 29

 

Các bước chính (rút gọn)

AddRoundKey (vòng 0): XOR plaintext với khóa ban đầu.

Vòng 1 → 9:

SubBytes: thay thế từng byte bằng giá trị trong SBox.

ShiftRows: dịch vòng các hàng trong ma trận.

MixColumns: trộn dữ liệu theo cột.

AddRoundKey: XOR với khóa vòng.

Vòng 10 (cuối):

SubBytes

ShiftRows

AddRoundKey (không có MixColumns).

Kết quả Ciphertext (16 byte):

39 25 84 1D 02 DC 09 FB DC 11 85 97 19 6A 0B 32

Giải mã sẽ đi ngược lại: bắt đầu với AddRoundKey bằng khóa vòng cuối, rồi lần lượt InvShiftRows, InvSubBytes, InvMixColumns, và AddRoundKey cho đến vòng 0.

Như vậy, em thấy rõ: cùng một plaintext và key, AES128 luôn cho ra ciphertext cố định. Điểm mạnh là nếu không có khóa, việc giải mã gần như bất khả thi.

Võ Nhật Trường+Ai NC

//////////////////////////////////////////////////////////////////

Không có nhận xét nào:

Đăng nhận xét

sunrise.tqb@gmail.com