Bài RSA giải bài toán trao khóa bằng cách mã hóa khóa AES rồi gửi. Diffie-Hellman (DH) làm một điều nghe như ảo thuật: hai bên cùng tính ra một khóa bí mật chung mà bí mật đó không bao giờ đi qua mạng — kể cả kẻ nghe lén toàn bộ cuộc trao đổi cũng không tính ra được. Đây là nền tảng trao khóa của TLS 1.3 và mọi kết nối HTTPS bạn dùng hằng ngày. Nghe kỳ diệu nhưng chứng minh được trong vài dòng openssl. Đo thật bằng X25519 (DH trên đường cong elliptic) với openssl 3.0.
Nghịch lý: chung bí mật qua kênh công khai
Bài toán: Alice và Bob muốn có chung một khóa để mã hóa (bằng AES), nhưng họ chỉ nói chuyện qua một kênh mà ai cũng nghe được. Làm sao thỏa thuận khóa mà không lộ? DH giải như sau:
- Mỗi bên sinh một cặp khóa (riêng + công khai).
- Hai bên trao khóa công khai cho nhau (công khai — nghe lén thoải mái).
- Mỗi bên tự tính:
derive(khóa_riêng_của_mình, khóa_công_khai_của_bên_kia).
Toán học của DH đảm bảo hai phép tính này ra cùng một giá trị bí mật S. Và mấu chốt: S chưa bao giờ được truyền đi — mỗi bên tự tính ra nó tại chỗ.
openssl genpkey -algorithm X25519 -out alice.pem # cặp khóa Alice
openssl pkey -in alice.pem -pubout -out alice.pub # khóa công khai Alice
openssl pkeyutl -derive -inkey alice.pem -peerkey bob.pub # Alice tính S

Hình 1: DH cho hai bên tính chung một bí mật S chỉ bằng khóa riêng của mình + khóa công khai của bên kia; S không bao giờ đi qua mạng. Kẻ nghe lén có cả hai khóa công khai vẫn không tính được S. Nền của TLS 1.3.
Đo thật: hai bên ra cùng một bí mật
Dùng X25519 (DH trên đường cong Curve25519). Alice và Bob mỗi bên sinh cặp khóa, chỉ trao khóa công khai, rồi mỗi bên derive:

Hình 2: Alice tính S = de2be5b5d3c93fd337bb3f20fd3268e6... từ khóa riêng Alice + công khai Bob; Bob tính từ khóa riêng Bob + công khai Alice ra giống hệt. Kẻ nghe lén có cả hai khóa công khai nhưng thiếu một khóa riêng nên không derive được S.
Kết quả đúng như lý thuyết:
- Alice (riêng Alice + công khai Bob) →
S = de2be5b5d3c93fd337bb3f20fd3268e6... - Bob (riêng Bob + công khai Alice) →
S = de2be5b5d3c93fd337bb3f20fd3268e6...— giống hệt. - Bí mật
S(32 byte) này chưa bao giờ truyền qua mạng. Chỉ hai khóa công khai đi qua dây. Hai bên giờ có chungSđể làm khóa AES mã hóa phần còn lại của cuộc trò chuyện. - Kẻ nghe lén chặn được cả
alice.publẫnbob.pub, nhưng để tínhScần một trong hai khóa riêng — mà khóa riêng không bao giờ rời máy chủ nhân. Bài toán "từ hai khóa công khai suy ra S" (Diffie-Hellman problem) là bất khả thi tính toán.
Đây chính xác là bước "key exchange" trong bắt tay TLS 1.3 (bài TLS ở sê-ri HTTP): ClientHello/ServerHello trao các khóa công khai DH tạm, hai bên derive ra khóa phiên, rồi mã hóa mọi thứ bằng AES-GCM.
Forward secrecy: vì sao dùng khóa tạm
Điểm mạnh lớn nhất của DH trong thực tế là forward secrecy (bí mật chuyển tiếp). Nếu mỗi phiên dùng một cặp khóa DH tạm thời (ephemeral — sinh mới rồi vứt sau phiên), thì kể cả sau này khóa dài hạn của server bị lộ, kẻ tấn công đã ghi lại lưu lượng cũ cũng không giải được — vì khóa DH tạm đã bị hủy, không tồn tại ở đâu để lấy. So với mô hình cũ (RSA bọc khóa: lộ khóa riêng RSA là giải được mọi phiên đã ghi), đây là bước tiến an ninh lớn. Đó là lý do TLS 1.3 bắt buộc dùng DH ephemeral (ECDHE), bỏ hẳn RSA key exchange.
Đánh đổi và lưu ý
DH thô KHÔNG chống man-in-the-middle (MITM). Đây là cạm bẫy chí mạng: DH đảm bảo hai bên có chung bí mật với người ở đầu kia, nhưng không đảm bảo đầu kia là ai. Kẻ MITM có thể tráo khóa công khai: nó làm DH riêng với Alice và một DH riêng với Bob, ngồi giữa giải mã–mã lại. Vì thế DH phải đi kèm xác thực danh tính — trong TLS, server ký các tham số DH bằng khóa riêng của chứng chỉ (bài chữ ký số + X.509), để Alice chắc chắn đang DH với đúng server chứ không phải kẻ giữa đường.
Dùng ephemeral, và đường cong/nhóm chuẩn. Ưu tiên ECDHE (như X25519) thay vì DH cổ điển (số nguyên lớn, chậm và tham số dễ đặt sai). Nếu dùng DH cổ điển, dùng nhóm chuẩn đủ lớn (≥2048-bit) — tham số yếu/dùng chung từng bị khai thác (Logjam). X25519 là lựa chọn hiện đại: nhanh, an toàn, ít cách cài sai.
DH chỉ trao khóa, chưa mã dữ liệu. Giống RSA/EC, DH lo phần "hai bên có chung khóa". Dữ liệu thật vẫn mã bằng AES-GCM với khóa S đó (thường qua một hàm dẫn khóa — KDF — để chuẩn hóa S thành khóa AES đúng độ dài).
Ba ý mang về
- Diffie-Hellman tạo bí mật chung mà không gửi nó qua mạng: đo thật, Alice (riêng Alice + công khai Bob) và Bob (riêng Bob + công khai Alice) cùng derive ra
de2be5b5...giống hệt; chỉ khóa công khai đi qua dây, kẻ nghe lén không tính đượcS. - Forward secrecy nhờ khóa tạm (ephemeral): mỗi phiên một cặp khóa DH mới rồi vứt → lộ khóa dài hạn sau này cũng không giải được phiên cũ đã ghi; đây là lý do TLS 1.3 bắt buộc ECDHE.
- DH thô không chống MITM: phải đi kèm xác thực (server ký tham số DH bằng chứng chỉ); dùng ECDHE/X25519 (hiện đại, khó cài sai) và dẫn khóa qua KDF trước khi làm khóa AES.
Nguồn
- Cloudflare — A Detailed Look at RFC 8446 (TLS 1.3) và key exchange/forward secrecy: https://blog.cloudflare.com/rfc-8446-aka-tls-1-3/
- OpenSSL docs — openssl-pkeyutl (mục -derive): https://docs.openssl.org/3.0/man1/openssl-pkeyutl/
Phần sau ta về nền móng mà mọi thứ trên dựa vào: sinh số ngẫu nhiên an toàn — khác biệt giữa random thường và CSPRNG, và vì sao dùng sai nguồn ngẫu nhiên phá vỡ cả hệ mật mã.