Mật mã cho lập trình viên: hiểu qua openssl
Sê-ri mật mã thực dụng cho lập trình viên — mỗi khái niệm demo bằng openssl chạy được, không toán hàn lâm.
12/12 phần đã đăng
Bảo mật
1
Hàm băm mật mã: dấu vân tay một chiều của dữ liệu — đo bằng openssl
Hàm băm biến dữ liệu bất kỳ thành một chuỗi cố định như dấu vân tay. Nhưng nhiều người nhầm nó là mã hóa. Bài mở đầu sê-ri mật mã đo thật bốn tính chất bằng openssl: cùng đầu vào cho cùng digest, đổi một ký tự thì digest khác hoàn toàn (chỉ 2/64 ký tự trùng), kích thước luôn cố định, và vì sao MD5 đã vỡ còn SHA-256 thì chưa.
22/09/2026
· 5 phút đọc
2
Vì sao KHÔNG lưu mật khẩu bằng SHA trần: salt, hàm cố ý chậm — đo thật
SHA-256 rất tốt để kiểm toàn vẹn, nhưng dùng nó lưu mật khẩu là sai lầm nguy hiểm — vì nó quá nhanh. Bài này đo thật: SHA-256 chạy 2,3 triệu hash/giây (kẻ bẻ khóa mơ ước), còn PBKDF2 cố ý chậm chỉ 10/giây — chậm hơn 231.000 lần mà người đăng nhập không hề thấy. Cùng salt để rainbow table vô dụng.
22/09/2026
· 5 phút đọc
3
HMAC: xác thực toàn vẹn kèm khóa bí mật — và vì sao đừng tự chế bằng SHA(key+msg)
Hash trần chỉ chống lỗi ngẫu nhiên, không chống kẻ địch: ai cũng sửa thông điệp rồi tính lại hash. HMAC trộn một khóa bí mật vào hàm băm nên chỉ người có khóa mới tạo được mã đúng. Bài này đo thật bằng openssl: sai khóa hay sửa một chữ số đều làm HMAC khác hẳn, và vì sao SHA256(key+msg) tự chế dính length-extension attack.
22/09/2026
· 5 phút đọc
4
AES và chế độ mã hóa: vì sao ECB lộ mẫu dữ liệu — thấy tận byte
AES mã hóa từng khối 16 byte; chế độ quyết định cách ghép các khối, và chọn sai thì mã hóa mà vẫn lộ thông tin. Bài này đo thật: cùng bốn khối giống hệt, ECB cho bốn khối mã GIỐNG HỆT (lộ mẫu — như ảnh chim cánh cụt kinh điển), còn CBC cho bốn khối khác nhau. Kèm vai trò của IV: cùng bản rõ, IV khác thì bản mã khác.
22/09/2026
· 5 phút đọc
5
AES-GCM: mã hóa vừa giấu vừa chống sửa — và vì sao nonce không được lặp
CBC giấu được nội dung nhưng không biết bản mã có bị sửa. AES-GCM giải quyết: mã hóa và tạo tag xác thực trong một bước, sửa một byte là giải mã từ chối. Bài này đo thật bằng python cryptography: bản mã kèm tag, tamper cho InvalidTag, và cái bẫy chết người — lặp nonce làm lộ XOR hai bản rõ mà không cần khóa.
22/09/2026
· 5 phút đọc
6
RSA: mã hóa bất đối xứng — hai khóa, và vì sao không mã được dữ liệu lớn
AES mã nhanh nhưng cả hai bên phải chung một khóa bí mật — làm sao trao khóa qua mạng không lộ? RSA giải: mỗi người một cặp khóa công khai + riêng. Bài này đo thật bằng openssl: ai cũng mã bằng khóa công khai, chỉ khóa riêng giải được; giải sai khóa thất bại; và giới hạn cốt tử — RSA chỉ mã được vài trăm byte nên thực tế dùng mã hóa lai.
22/09/2026
· 5 phút đọc
7
Đường cong elliptic (EC): vì sao khóa 256-bit mạnh ngang RSA 3072 — đo thật
RSA khóa càng dài càng chậm và cồng kềnh. Đường cong elliptic đạt cùng mức an toàn với khóa nhỏ hơn nhiều nhờ dựa trên một bài toán khó khác. Bài này đo thật bằng openssl: khóa riêng EC P-256 chỉ 241 byte so với RSA 3072 là 2484 byte, và ECDSA ký nhanh hơn RSA tới ~90 lần — kèm đánh đổi RSA verify vẫn nhanh hơn.
22/09/2026
· 5 phút đọc
8
Chữ ký số: ký bằng khóa riêng, ai cũng xác thực bằng khóa công khai
Làm sao chứng minh một file/token/bản cập nhật đúng do bạn tạo và chưa bị sửa, mà ai cũng kiểm được nhưng không ai giả được? Chữ ký số: dùng cặp khóa NGƯỢC với mã hóa — ký bằng khóa riêng, xác thực bằng khóa công khai. Bài này đo thật bằng openssl: ký OK, sửa một ký tự thì verify thất bại, sai khóa công khai cũng thất bại — và khác HMAC ở chống chối bỏ.
22/09/2026
· 5 phút đọc
9
Diffie-Hellman: tạo bí mật chung mà không hề gửi nó qua mạng — đo thật
RSA giải bài trao khóa bằng cách mã khóa AES rồi gửi. Diffie-Hellman làm điều còn ảo diệu hơn: hai bên tự tính ra CÙNG một khóa bí mật mà bí mật đó không bao giờ đi qua mạng. Bài này đo thật bằng openssl X25519 — Alice và Bob mỗi bên chỉ dùng khóa riêng của mình + khóa công khai của người kia, cho ra hai giá trị giống hệt nhau. Kèm forward secrecy và bẫy MITM.
22/09/2026
· 6 phút đọc
10
Sinh số ngẫu nhiên an toàn: vì sao random() thường phá vỡ cả hệ mật mã
Mọi thứ trong mật mã — khóa, salt, IV, nonce, token — đều dựa vào ngẫu nhiên KHÔNG đoán được. Nhưng random() thường là tất định: cùng seed cho cùng dãy. Bài này đo thật bằng python: random.seed(42) ra y hệt hai lần, token sinh bằng seed=timestamp tái tạo được; còn secrets/os.urandom/openssl rand thì không đoán nổi. Dùng sai nguồn ngẫu nhiên là lỗ hổng nghiêm trọng.
22/09/2026
· 5 phút đọc
11
Mã hóa file bằng mật khẩu: ghép AES, PBKDF2 và salt lại — đo thật bằng openssl
Người dùng nhớ mật khẩu, nhưng AES-256 cần khóa nhị phân 32 byte — khoảng cách đó do hàm dẫn khóa (KDF) lấp. Bài này mã hóa một file thật bằng openssl với AES-256-CBC + PBKDF2: xem header Salted__ tự chứa salt, giải mã đúng ra nội dung còn sai mật khẩu thì bad decrypt, và cùng file+mật khẩu hai lần cho bản mã khác nhau nhờ salt ngẫu nhiên.
22/09/2026
· 5 phút đọc
12
TOTP: mã 6 số của xác thực hai lớp thực ra là gì — tự tính bằng python
Mã 6 số đổi mỗi 30 giây trên Google Authenticator không hề được server gửi tới điện thoại. Nó là HMAC-SHA1 của bí mật chung với thời gian, cắt lấy 6 chữ số. Bài cuối sê-ri mật mã tự tính TOTP từ đầu bằng python theo RFC 6238: cùng bí mật + cùng mốc thời gian cho cùng mã, mã không đổi trong cửa sổ 30s rồi đổi sang cửa sổ mới.
22/09/2026
· 6 phút đọc