Trình duyệt biết đúng máy chủ bằng cách nào?
Làm sao trình duyệt biết đầu bên kia đúng là example.com?
TLS có thể mã hoá dữ liệu để người đứng giữa không đọc được.
Nhưng vẫn còn một vấn đề.
Giả sử bạn muốn kết nối tới:
example.com
Một kẻ đứng giữa chặn kết nối, rồi tự bắt tay TLS với trình duyệt của bạn.
Kết nối vẫn có thể được mã hoá hoàn toàn bình thường.
Chỉ có điều bạn đang mã hoá dữ liệu cho nhầm người.
Vậy trình duyệt biết đầu bên kia thật sự là example.com bằng cách nào?
Một khoá công khai chưa chứng minh được gì
Máy chủ có một cặp khoá:
khoá riêng
khoá công khai
Khoá riêng (private key) được máy chủ giữ bí mật.
Khoá công khai (public key) có thể đưa cho bất kỳ ai.
Máy chủ có thể dùng khoá riêng để tạo chữ ký. Người khác dùng khoá công khai tương ứng để kiểm tra chữ ký đó.
Nếu trình duyệt biết chắc một khoá công khai thuộc về example.com, nó có thể yêu cầu máy chủ chứng minh rằng mình đang giữ khoá riêng tương ứng.
Nhưng vấn đề nằm ở chữ “biết chắc”.
Kẻ giả mạo cũng có thể tự tạo một cặp khoá:
khoá riêng của kẻ giả mạo
khoá công khai của kẻ giả mạo
rồi gửi khoá công khai của hắn và nói:
Đây là khoá công khai của example.com.
Nếu trình duyệt tin luôn thì cơ chế này chẳng giúp được gì.
Trình duyệt cần một cách để xác minh:
example.com
↓
khoá công khai này thật sự thuộc về tên miền đó
Đó là lý do chứng chỉ số tồn tại.
Chứng chỉ nối tên miền với khoá công khai
Khi truy cập một website HTTPS, máy chủ gửi cho trình duyệt một chứng chỉ số (certificate).
Có thể hình dung bên trong nó có những thông tin như:
Tên miền: example.com
Khoá công khai: ...
Có hiệu lực từ: ...
Có hiệu lực đến: ...
Được cấp bởi: ...
Chữ ký của bên cấp: ...
Điểm quan trọng là chứng chỉ không chỉ nói:
Đây là khoá công khai của example.com.
Nó còn có chữ ký của một tổ chức cấp chứng chỉ (CA, Certificate Authority).
CA chỉ ký sau khi đã xác minh người xin chứng chỉ có quyền kiểm soát tên miền đó.
Vì vậy kẻ giả mạo có thể tự tạo một chứng chỉ ghi example.com, nhưng hắn không thể tự tạo chữ ký hợp lệ của một CA mà trình duyệt tin cậy.
Nhưng điều này lại dẫn tới câu hỏi tiếp theo:
Tại sao trình duyệt lại tin CA?
Trình duyệt đã có sẵn những CA mà nó tin
Trình duyệt hoặc hệ điều hành có sẵn một danh sách các CA gốc (root CA) được tin cậy.
Nó không tải danh sách này từ Internet mỗi lần bạn mở một website.
Trình duyệt đã biết trước:
Tôi tin khoá công khai của những CA gốc này.
CA gốc thường không dùng khoá của mình để ký trực tiếp hàng triệu chứng chỉ website.
Thay vào đó, nó ký cho các CA trung gian (intermediate CA).
CA trung gian mới dùng khoá của mình để ký chứng chỉ cho website.
Chuỗi có dạng:
CA gốc
↓ ký
CA trung gian
↓ ký
example.com
Khi kết nối tới example.com, máy chủ thường gửi chứng chỉ của mình cùng những chứng chỉ trung gian cần thiết.
Trình duyệt kiểm tra từng chữ ký ngược lên trên:
chứng chỉ example.com
↓
được CA trung gian ký?
↓
chứng chỉ của CA trung gian
↓
được một CA phía trên ký?
↓
...
↓
CA gốc có nằm trong danh sách tin cậy?
Nếu cuối cùng chuỗi dẫn tới một CA gốc mà trình duyệt đã tin sẵn, phần chữ ký của chuỗi chứng chỉ hợp lệ.

Trình duyệt còn kiểm tra tên miền và thời hạn
Một chuỗi chữ ký hợp lệ vẫn chưa đủ.
Trình duyệt còn phải kiểm tra chứng chỉ có thực sự dùng được cho kết nối hiện tại hay không.
Ví dụ bạn đang mở:
https://example.com
thì chứng chỉ phải hợp lệ cho example.com.
Nếu máy chủ đưa chứng chỉ của:
another-site.com
thì dù chứng chỉ đó hoàn toàn thật, trình duyệt vẫn không chấp nhận.
Chứng chỉ cũng chỉ có hiệu lực trong một khoảng thời gian nhất định.
Vì vậy, ở mức đơn giản, trình duyệt đang kiểm tra ba việc:
1. Chuỗi chữ ký có dẫn tới một CA gốc đáng tin không?
2. Chứng chỉ có được cấp cho example.com không?
3. Chứng chỉ hiện tại còn hiệu lực không?
Sai một bước, trình duyệt có thể hiện cảnh báo chứng chỉ.
Nhưng kẻ giả mạo có thể copy chứng chỉ thật mà?
Có.
Chứng chỉ không phải bí mật.
Bất kỳ ai kết nối tới example.com cũng có thể lấy chứng chỉ mà máy chủ gửi ra.
Kẻ giả mạo hoàn toàn có thể copy nguyên chứng chỉ thật của example.com rồi đưa nó cho trình duyệt.
Chứng chỉ vẫn có:
đúng tên miền
đúng chuỗi CA
đúng thời hạn
Vậy tại sao hắn vẫn không giả được example.com?
Bởi vì chứng chỉ chỉ chứa khoá công khai.
Kẻ giả mạo không có khoá riêng tương ứng.
Trong quá trình bắt tay TLS, máy chủ phải tạo một chữ ký bằng khoá riêng của mình trên các thông tin của phiên bắt tay.
Trình duyệt lấy khoá công khai trong chứng chỉ để kiểm tra chữ ký đó.
Nếu chữ ký đúng, trình duyệt biết hai chuyện:
CA xác nhận:
khoá công khai này thuộc về example.com
Máy chủ vừa chứng minh:
tôi đang giữ khoá riêng tương ứng
Kẻ chỉ copy chứng chỉ có khoá công khai, nhưng không có khoá riêng.
Vì vậy hắn không tạo được chữ ký cần thiết.
Toàn bộ quá trình ghép lại
Có thể rút gọn quá trình xác minh thành:
Trình duyệt muốn vào example.com
↓
Máy chủ gửi chứng chỉ
↓
Trình duyệt kiểm tra:
- đúng example.com?
- còn hạn?
- chuỗi chữ ký có dẫn tới CA tin cậy?
↓
Trình duyệt lấy khoá công khai trong chứng chỉ
↓
Máy chủ dùng khoá riêng ký dữ liệu bắt tay
↓
Trình duyệt kiểm tra chữ ký bằng khoá công khai
↓
Khớp
↓
Máy chủ đang giữ khoá riêng
của chứng chỉ dành cho example.com
Sau khi xác minh xong, hai bên tiếp tục thiết lập khoá phiên dùng để mã hoá dữ liệu.

Chứng chỉ và khoá riêng vì thế làm hai việc khác nhau:
Chứng chỉ:
khoá công khai này được xác nhận cho example.com
Khoá riêng:
máy chủ trước mặt thực sự đang giữ khoá tương ứng
HTTPS không có nghĩa website đó đáng tin
Có một điều rất dễ nhầm.
Chứng chỉ hợp lệ không có nghĩa website đó là website tốt, an toàn hay thuộc về một công ty uy tín.
Ví dụ một kẻ lừa đảo sở hữu tên miền:
my-bank.example
Hắn hoàn toàn có thể xin một chứng chỉ hợp lệ cho chính tên miền đó.
Khi bạn truy cập:
https://my-bank.example
trình duyệt có thể xác minh chính xác rằng:
Bạn đang kết nối tới my-bank.example.
Nhưng chứng chỉ không biết my-bank.example có phải ngân hàng mà bạn định truy cập hay không.
HTTPS trả lời câu hỏi:
Tôi có đang kết nối tới đúng tên miền trên thanh địa chỉ không?
Nó không trả lời:
Tôi có nên tin chủ của tên miền này không?
Đến đây, trình duyệt đã có thể xác minh máy chủ và thiết lập một kết nối được mã hoá.
Nhưng cuối cùng những bit đã mã hoá đó vẫn phải rời laptop và đi tới router.
Nếu bạn đang dùng Wi-Fi, giữa hai thiết bị thậm chí còn không có sợi dây nào.
Vậy những bit đó đi qua căn phòng bằng cách nào?
Nguồn bài viết (6)
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3 · IETF
- RFC 5280 — Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile · IETF
- RFC 9525 — Service Identity in TLS · IETF
- Let's Encrypt — Chains of Trust · Let's Encrypt
- Phishing and Malware (certificate không bảo chứng website) · Let's Encrypt
- Leaving Beta, New Sponsors (12/4/2016) · Let's Encrypt