Câu trả lời đúng về mật mã học thời hậu lượng tử: Cẩm nang cho lập trình viên 2026
Bài viết cập nhật loạt khuyến nghị mật mã học kinh điển dành cho lập trình viên, phản ánh bước ngoặt lớn của quá trình chuyển đổi hậu lượng tử với hạn chót năm 2029. Mật mã đối xứng vẫn an toàn nhờ Grover không đáng lo, nhưng gần như toàn bộ câu trả lời về mật mã bất đối xứng đã thay đổi so với các phiên bản 2018 và 2024.

Câu trả lời đúng về mật mã học thời hậu lượng tử: Cẩm nang cho lập trình viên 2026
Mật mã học hậu lượng tử
Việc công bố danh sách "Câu trả lời đúng về mật mã học" (Cryptographic Right Answers) cho lập trình viên đã trở thành một truyền thống. Colin Percival khởi xướng năm 2009, Thomas Ptacek tiếp nối năm 2015, rồi Latacora duy trì vào các năm 2018 và 2024.
Có thể bạn nghĩ còn quá sớm để cập nhật, nhưng mọi thứ đã thay đổi quá nhiều. Dòng thời gian của quá trình chuyển đổi hậu lượng tử đã dịch chuyển mạnh mẽ vào đầu năm 2026, và hiện đã có đồng thuận rằng quá trình này phải hoàn tất trước năm 2029. Năm 2029! Chúng ta chỉ còn ba năm!
Tin tốt là, bất chấp những gì bạn có thể đã nghe, mật mã đối xứng sẽ vẫn ổn, vì thuật toán Grover không thực sự đáng lo. Tin xấu là mọi câu trả lời về mật mã bất đối xứng đều đã thay đổi so với năm 2018, và hầu hết thậm chí so với năm 2024.
Các khuyến nghị dưới đây giả định bạn không bị ràng buộc bởi bất kỳ chế độ tuân thủ cụ thể nào, dù chúng phần lớn tương thích với FIPS 140. Nếu bạn cần tuân theo những chuẩn nghiêm ngặt hơn như CNSA 2.0, bạn sẽ tự biết. Cuối cùng, hãy nhớ một thay đổi lớn khác của năm 2026: các mô hình ngôn ngữ lớn (LLM) giờ đây rất giỏi trong việc tìm lỗi.
"Hãy nhờ mô hình tốt nhất mà bạn có thể chi trả để review code" giờ đây đã chính thức trở thành một câu trả lời đúng về mật mã học, song hành cùng lời khuyên kinh điển từ lâu: "hãy dùng ngôn ngữ có quản lý bộ nhớ an toàn."
Bảng tóm tắt nhanh
Nếu bạn đang gấp, đây là bảng tóm tắt:
- Mã hóa dữ liệu: Nếu dùng cloud, dùng KMS. Nếu không, dùng XAES-256-GCM hoặc XChaCha20Poly1305 với nonce ngẫu nhiên. Nếu mã hóa trên vài MB, dùng Cobblestone-128.
- Độ dài khóa đối xứng: Đừng căng thẳng. Chọn khóa 256-bit nếu cần chọn.
- "Chữ ký" đối xứng: HMAC-SHA-256.
- Thuật toán băm: SHA-2 vẫn ổn, nhưng dùng multihash thực thụ (SequenceHash) nếu cần.
- ID ngẫu nhiên: 32 byte ngẫu nhiên, tức số ngẫu nhiên 256-bit.
- Xử lý mật khẩu: Argon2id hoặc scrypt. Nhưng bạn đã cân nhắc dùng passkey chưa?
- Trao đổi khóa: X25519+ML-KEM-768 trong một giao thức chuẩn, an toàn.
- Mã hóa bất đối xứng: HPKE với (MLKEM768-X25519 hay còn gọi X-Wing, HKDF-SHA256, AES-128-GCM), hoặc age với khóa PQ.
- Chữ ký bất đối xứng: ML-DSA-44.
- Bảo mật website hoặc ứng dụng client-server: Nếu dùng cloud, dùng ALB/NLB. Nếu không, dùng rustls, crypto/tls của Go, BoringSSL, AWS-LC, hoặc s2n-tls kèm một ACME client phổ biến, được cập nhật.
- Sao lưu trực tuyến: restic với mật khẩu ngẫu nhiên dài.
Mã hóa dữ liệu
Khuyến nghị qua các thời kỳ:
- Percival, 2009: AES-CTR với HMAC.
- Ptacek, 2015: Mặc định NaCl/libsodium, hoặc ChaCha20Poly1305, hoặc AES-GCM.
- Latacora, 2018: KMS, hoặc XSalsa20+Poly1305.
- Latacora, 2024: KMS, hoặc secretbox của NaCl, hoặc XChaCha20Poly1305.
Lý do dùng KMS của cloud vẫn còn nguyên giá trị, nên hãy bắt đầu từ đó.
Nếu mã hóa cục bộ, bạn cần một AEAD mà bạn không phải lo lắng về việc theo dõi nonce hay số lượng thông điệp đã mã hóa, nên bạn cần nonce ngẫu nhiên tối thiểu 128 bit.
Secretbox của NaCl/libsodium chỉ là lớp bọc mỏng quanh một cấu trúc AEAD ít phổ biến hơn (XSalsa20+Poly1305), nên thay vào đó tôi khuyến nghị XAES-256-GCM hoặc XChaCha20Poly1305. Cấu trúc thứ nhất là sự kết hợp hiệu quả giữa một KDF chuẩn và AES-GCM, được đóng gói như một AEAD nonce mở rộng.
AES-GCM và ChaCha20Poly1305 thông thường với nonce ngẫu nhiên chỉ ổn nếu bạn chắc chắn không mã hóa quá một tỷ thông điệp với cùng một khóa.
Vì đã có AEAD, hãy cân nhắc đặt ngữ cảnh vào dữ liệu bổ sung, ví dụ ID người dùng mà bạn đang mã hóa cho họ, hoặc phiên bản của giao thức.
Rất quan trọng là cách xử lý thông điệp lớn — điều mà KMS không giải quyết giúp bạn. Tuyệt đối không dùng các stream cipher chưa xác thực. Thay vào đó, bạn nên dùng STREAM (không phải stream cipher mà là cách dùng AEAD trên luồng dữ liệu). Tôi khuyến nghị Cobblestone-128, một biến thể STREAM bắt nguồn từ TLS, đã có trong pyca/cryptography và sắp có trong thư viện chuẩn của Go.
- Nên tránh: các chế độ chưa xác thực (CBC, CTR, stream cipher thô), nonce 96-bit ngẫu nhiên trừ khi bạn đã suy nghĩ kỹ về số thông điệp mã hóa, tự chế cấu trúc AEAD.
Độ dài khóa đối xứng
Đừng căng thẳng. Chọn khóa 256-bit nếu cần chọn.
Hãy nhớ rằng Grover không thực sự đáng lo và các cuộc tấn công brute-force 128-bit không tồn tại. Dù vậy, khóa 256-bit loại trừ các cuộc tấn công đa mục tiêu, điều này rất hay.
Tuy nhiên, đừng đưa ra các quyết định khác dựa trên điều này. Ví dụ, bộ Cobblestone được khuyến nghị dùng khóa 128-bit và điều đó hoàn toàn ổn vì nó có phân tích cẩn thận về tấn công đa mục tiêu.
- Nên tránh: bất cứ thứ gì khác ngoài 128 hoặc 256 bit, lo lắng quá nhiều về kích thước, khóa không đồng nhất (ví dụ dùng mật khẩu hoặc chuỗi hex ASCII trực tiếp làm khóa).
"Chữ ký" đối xứng
HMAC-SHA-256.
Cả bốn phiên bản khuyến nghị đều thống nhất: HMAC. Hãy cẩn thận tránh các lỗi về canonicalization và căn chỉnh parser bằng cách luôn xác thực một chuỗi byte nguyên văn, không phải thứ bạn cần tính toán lại.
Tốt:
{
"inner": "{\"foo\":123}",
"hmac": "MbPsZq7QGCllJgDnSSy/cyM10HjqiVu35UO7yyY5d3w="
}
Hãy kiểm tra HMAC rồi mới xử lý, lưu trữ hoặc chuyển tiếp chỉ {"foo":123}.
Xấu: đặt trường hmac lẫn vào chính đối tượng cần xác thực.
Bạn có thể dùng KMAC hoặc BLAKE3 có khóa nếu đã có lý do dùng hàm băm nền của chúng. HMAC-SHA-512 cũng ổn.
- Nên tránh: tự chế YoloMAC, băm đã mã hóa, các MAC dùng một lần độc lập như Poly1305 hay GMAC.
Thuật toán băm
SHA-2 vẫn ổn, nhưng dùng multihash thực thụ nếu cần.
Lựa chọn tốt nhất, nếu có sẵn, vẫn là SHA-512/256, không bị lỗ hổng tấn công mở rộng độ dài. Nếu không, SHA-256 và SHA-512 đều ổn.
SHA-3 là không cần thiết (vì SHA-2 đã ổn) và chậm, nhưng không sai. Nếu bạn đã có Keccak (SHA-3) quanh đó cho ML-KEM và ML-DSA, và muốn dùng để băm, hãy lấy 32 byte từ SHAKE128.
BLAKE2 là lựa chọn kỳ lạ ngày nay. BLAKE3 rất nhanh nhưng phức tạp và ít phổ biến.
- Nên tránh: SHA-1, MD5, mọi hàm băm khác, tự chế multihash, cắt ngắn xuống dưới 256 bit trừ khi chuyên gia mật mã nói rằng xung đột không đáng lo.
ID ngẫu nhiên
32 byte ngẫu nhiên, tức số ngẫu nhiên 256-bit.
Lưu ý rằng UUIDv4 và các API như rand.Text chỉ cho bạn giá trị ~128-bit. Điều đó thường ổn, trừ khi bạn cần hơn 280 nghìn tỷ (2⁴⁸) giá trị duy nhất. 256 bit là hơi quá, nhưng tại sao không.
Hãy dùng CSPRNG của hệ điều hành: getrandom trên Linux, ProcessPrng trên Windows, arc4random_buf trên macOS và BSD, getRandomValues trên web.
- Nên tránh: PRNG phi mật mã, bộ sinh số ngẫu nhiên không gian người dùng như của OpenSSL, haveged, entropy từ jitter CPU.
Xử lý mật khẩu
Argon2id hoặc scrypt. Nhưng bạn đã cân nhắc dùng passkey chưa?
- Percival, 2009: scrypt hoặc PBKDF2.
- Ptacek, 2015: scrypt, rồi bcrypt, rồi PBKDF2 nếu buộc phải.
- Latacora, 2018: scrypt, rồi Argon2, rồi bcrypt, rồi PBKDF2 nếu buộc phải.
- Latacora, 2024: Argon2id, rồi scrypt, rồi bcrypt, rồi PBKDF2 nếu buộc phải.
Tôi đã bỏ bcrypt vì việc cắt ngắn ở 72 byte gây hại. Về tham số, hãy bỏ qua RFC 9106 (vốn dường như muốn giết chết hệ thống production của bạn), và dùng m=64 MiB, t=2, p=1 cho Argon2id (preset INTERACTIVE của libsodium) hoặc N=2^16, r=8, p=1 cho scrypt.
Quan trọng hơn nhiều: bạn có thực sự cần mật khẩu không? Nếu chỉ cần cho đăng nhập, bạn có thể dùng passkey chống lừa đảo thay thế không? Có thể kèm email magic link làm phương án dự phòng? Hoặc chỉ hỗ trợ SSO (miễn là OIDC chứ không phải SAML)?
- Nên tránh: các hàm băm thông thường, tốn thời gian nghĩ về hàm băm mật khẩu thay vì tập trung vào passkey, các biến thể đăng nhập qua email dễ bị lừa đảo.
Trao đổi khóa
X25519+ML-KEM-768 trong một giao thức chuẩn, an toàn.
- Percival, 2009: Group #14 2048-bit với generator bằng 2.
- Ptacek, 2015: Có lẽ vẫn là DH-2048, hoặc NaCl.
- Latacora, 2018: Có lẽ không có gì. Hoặc Curve25519.
- Latacora, 2024: X25519+ML-KEM-768.
Các giải pháp không hậu lượng tử hiện là mối nguy hiểm cấp bách do các cuộc tấn công kiểu "thu hoạch ngay, giải mã sau". Với trao đổi khóa, dùng hybrid ECC là đủ rẻ để đáng làm, và thực tế ML-KEM thường được triển khai song song với ECDH.
Tuy nhiên, nếu việc chọn hoặc triển khai hybrid khiến bạn chậm trễ dù chỉ một tháng so với trao đổi khóa cổ điển, hãy chuyển thẳng sang ML-KEM-768 thuần ngay bây giờ.
- Nên tránh: mọi thứ không có ML-KEM hoặc X-Wing trong tên.
Mã hóa bất đối xứng
HPKE với (MLKEM768-X25519 hay X-Wing, HKDF-SHA256, AES-128-GCM), hoặc age với khóa PQ.
- Percival, 2009: RSAES-OAEP với SHA-256, MGF1+SHA-256, số mũ 65537.
- Ptacek, 2015: NaCl.
- Latacora, 2018: NaCl/libsodium (box / crypto_box).
- Latacora, 2024: Khó xử, chờ các giải pháp PQ đã được thiết lập.
Đây là một trong những câu trả lời được cải thiện nhiều nhất trong những năm gần đây, vì giờ chúng ta đã có chuẩn để làm mã hóa hybrid: HPKE.
Lưu ý rằng các KEM PQ cho HPKE vẫn còn ở dạng draft, và tệ hơn là bị phân tán không cần thiết trên bốn bản draft khác nhau. Tuy nhiên, các tác giả đã cam kết không thay đổi định dạng đường truyền, nên bạn có thể và nên dùng chúng.
Nếu cần thứ gì đó cấp cao hơn, với nhiều người nhận hoặc CLI, hãy dùng age với các khóa tiền tố age1pq- mới, dựa trên MLKEM768-X25519.
- Nên tránh: một lần nữa, bất cứ thứ gì không dựa trên ML-KEM (đặc biệt là RSA và box của NaCl), OpenPGP, mã hóa email.
Chữ ký bất đối xứng
ML-DSA-44.
- Percival, 2009: RSASSA-PSS với SHA-256, MGF1+SHA-256, số mũ 65537.
- Ptacek, 2015: NaCl, Ed25519, hoặc RFC 6979.
- Latacora, 2018: NaCl hoặc Ed25519.
- Latacora, 2024: Ed25519 nếu ngắn hạn, ngược lại Ed25519+ML-DSA-65.
Vào tháng 1 năm 2026, tôi sẽ khuyên bạn chờ xem, nhưng rồi mọi thứ bắt đầu chuyển động nhanh hơn nhiều. Bạn cũng cần chuyển sang PQ cho xác thực.
Chỉ cần dùng ML-DSA-44. Nếu thông điệp của bạn cần băm trước, hãy dùng ký "external-μ (Mu)", không dùng HashML-DSA. Chỉ lưu khóa dưới dạng seed 32 byte.
Tại sao không dùng hybrid hay "composite"? Xác thực hybrid phức tạp hơn và ít hữu ích hơn trao đổi khóa hybrid. ML-DSA là một thuật toán chữ ký tốt hơn hẳn các tiền bối: nó có tính ngẫu nhiên hedged, ngữ cảnh tích hợp, và các thuộc tính bổ sung như SUF-CMA.
Một ngoại lệ cho quy tắc không composite là khóa SSH. OpenSSH 10.6 đã chọn ssh-mldsa44-ed25519. Tôi nghĩ họ đã sai lầm, nhưng bạn đi chệch khỏi con đường phổ biến ở đó cũng là sai lầm.
- Nên tránh: tất cả các lựa chọn không PQ như RSA/ECDSA/Ed25519, chữ ký có trạng thái (LMS/XMSS), HashML-DSA, khóa "bán mở rộng" của ML-DSA, chữ ký composite, OpenPGP.
Bảo mật website hoặc ứng dụng client-server
Nếu dùng cloud, dùng ALB/NLB. Nếu không, dùng rustls, crypto/tls của Go, BoringSSL, AWS-LC, hoặc s2n-tls kèm một ACME client phổ biến, được cập nhật.
Việc không khuyến nghị OpenSSL có lẽ là gợi ý kém thực tế nhất của tôi, nhưng OpenSSL đã đưa ra những lựa chọn khó hiểu và có vấn đề một cách nhất quán trong nhiều năm nay.
Tôi khuyến nghị rustls hoặc crypto/tls của Go, đều an toàn về bộ nhớ. Nếu buộc phải dùng C, cả BoringSSL và AWS-LC đều là các bản fork OpenSSL được duy trì rất tốt, và AWS-LC có phát hành phiên bản (khác với BoringSSL).
Dù dùng gì, hãy đảm bảo nó ưu tiên trao đổi khóa X25519MLKEM768, vốn yêu cầu TLS 1.3. Cân bằng tải cloud của bạn có thể yêu cầu bạn chọn chính sách bảo mật PQ.
- Nên tránh: tự chế giao thức truyền tải, các thư viện TLS từng thất bại trong nhiệm vụ cốt lõi (GnuTLS, Mbed TLS, wolfSSL, Botan), các thư viện TLS lạ, OpenSSL trước phiên bản 3.5 (bản đầu tiên có X25519MLKEM768), bất kỳ OpenSSL nào nếu có thể, TLS 1.0–1.1, TLS 1.2 nếu có thể, tự chế ACME client.
Sao lưu trực tuyến
restic với mật khẩu ngẫu nhiên dài.
- Percival, 2009: Tarsnap.
- Ptacek, 2015: Tarsnap.
- Latacora, 2018: Tarsnap.
- Latacora, 2024: Tarsnap.
Tôi đã kiểm tra mã hóa của restic từ rất lâu và nó hơi lạ nhưng tốt. Hoàn toàn đối xứng, nên không sợ máy tính lượng tử. Nếu cần lưu trữ cloud, rsync.net có gói "secret" cho người dùng restic, hỗ trợ chế độ chỉ thêm (append-only).
Tất cả chúng ta đều yêu Tarsnap, nhưng lớp mật mã bất đối xứng của nó hoàn toàn là RSA. Về mặt kỹ thuật, tôi nghĩ chỉ những khóa có khả năng thấp hơn mới thực sự bị phá vỡ. Tuy nhiên, điều này giống như một cái bẫy lớn với máy tính lượng tử đang đến gần.
Kết luận
Quá trình chuyển đổi hậu lượng tử đang diễn ra nhanh hơn nhiều so với dự đoán, với hạn chót năm 2029 chỉ còn ba năm nữa. Đối với các nhà phát triển tại Việt Nam đang xây dựng ứng dụng, các điểm cần lưu ý ngay:
- Kiểm tra phiên bản thư viện mật mã và đảm bảo hỗ trợ ML-KEM, ML-DSA.
- Ưu tiên trao đổi khóa hybrid X25519+ML-KEM-768 trong TLS 1.3.
- Chuyển dần sang passkey thay vì mật khẩu truyền thống.
- Xem xét migrate khỏi RSA cho chữ ký và mã hóa bất đối xứng.
- Dùng ngôn ngữ an toàn bộ nhớ như Rust hoặc Go cho mọi thành phần mật mã.
Mật mã hậu lượng tử là tương lai
Với các tổ chức Việt Nam đang số hóa mạnh mẽ, việc nắm bắt làn sóng chuyển đổi hậu lượng tử từ sớm sẽ giúp tránh được những rủi ro tốn kém trong những năm tới.
Bài viết liên quan

Công nghệ
Codex CLI tự động cài tiến trình nền thường trú: Tiện lợi hay mối lo bảo mật?
12 tháng 10, 2026

Công nghệ
GitHub Copilot cho người mới bắt đầu: Cách dạy Copilot hiểu về codebase của bạn
12 tháng 10, 2026
Công nghệ
Siêu phẩm kinh dị P.T. của Kojima cuối cùng cũng có bản port chơi được trên PC
12 tháng 10, 2026