Bạn đang ngồi trên máy bay, điện thoại bật chế độ máy bay, không Wi-Fi, không 4G. Một trang web đòi mã xác thực hai lớp, bạn mở Google Authenticator và nó vẫn hiện ra sáu chữ số, gõ vào là đăng nhập được ngay. Không có mạng thì mã ấy lấy từ đâu? Có phải ứng dụng lén lưu sẵn cả nghìn mã, hay nó vẫn âm thầm nói chuyện với server của Google? Bài này mổ xẻ từng bước, từ lúc bạn quét mã QR đến lúc sáu con số hiện lên, để bạn hiểu vì sao nó chạy được offline và chỗ nào thật sự cần cẩn thận.
Mã 6 số thực ra đến từ đâu?
Câu trả lời ngắn: không đến từ đâu cả, nó được tính ngay trên điện thoại của bạn. Google Authenticator không tải mã về, cũng không gửi gì đi khi tạo mã. Nó chỉ làm một phép tính từ hai nguyên liệu:
- Khoá bí mật (secret key): một chuỗi ngẫu nhiên mà website và điện thoại cùng giữ một bản.
- Thời gian hiện tại: lấy từ đồng hồ trong máy.
Cách làm này có tên chuẩn là TOTP (Time-based One-Time Password, mật khẩu dùng một lần dựa trên thời gian), được IETF công bố trong tài liệu RFC 6238 năm 2011. TOTP lại xây trên nền HOTP (RFC 4226, năm 2005), phiên bản dùng bộ đếm thay cho đồng hồ. Google Authenticator chỉ là một ứng dụng cài đặt chuẩn mở này, nên bạn quét cùng một mã QR vào Microsoft Authenticator, Aegis hay 2FAS thì đều ra đúng cùng một dãy số.
Ý tưởng "thiết bị tự sinh mã theo thời gian" thậm chí có từ trước smartphone rất lâu. Các ngân hàng và doanh nghiệp từng phát cho nhân viên những chiếc token phần cứng nhỏ bằng móc khoá, màn hình LCD nhảy số liên tục, chẳng có ăng-ten hay cổng mạng nào.

Hãy hình dung bạn và ngân hàng mỗi bên có một chiếc máy tính bỏ túi giống hệt nhau, cài sẵn cùng một công thức bí mật. Cứ mỗi 30 giây, cả hai bấm cùng một phép tính với giờ hiện tại. Không ai cần gọi điện cho ai, nhưng kết quả luôn trùng nhau.
Lần "bắt tay" duy nhất: quét mã QR
Mọi thứ bắt đầu khi bạn bật xác thực hai lớp trên một website. Server tạo ngẫu nhiên một khoá bí mật cho riêng tài khoản của bạn, lưu lại một bản, rồi hiển thị nó dưới dạng mã QR.

Bên trong mã QR thực chất chỉ là một dòng chữ theo định dạng URI, đại loại:
otpauth://totp/TenWebsite:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=TenWebsite&digits=6&period=30
Trong đó:
- secret: khoá bí mật, viết bằng mã Base32 (chỉ gồm chữ A–Z và số 2–7, dễ gõ tay). Thường dài 16 hoặc 32 ký tự, tương đương 80 hoặc 160 bit ngẫu nhiên.
- digits=6: độ dài mã.
- period=30: mỗi mã sống 30 giây.
Đây là lần duy nhất khoá bí mật đi qua màn hình. Sau khi bạn quét xong và gõ thử một mã để xác nhận, khoá nằm yên trong bộ nhớ ứng dụng, còn bản kia nằm trong cơ sở dữ liệu của website. Từ đó về sau, hai bên không bao giờ trao đổi khoá nữa.
Ai chụp được mã QR (hoặc chuỗi secret) lúc bạn thiết lập là có thể tạo mã của bạn vĩnh viễn, cho đến khi bạn tắt rồi bật lại 2FA. Đừng chụp màn hình mã QR gửi qua chat, đừng lưu nó trong thư mục ảnh đồng bộ đám mây.
Đồng hồ biến thời gian thành con số như thế nào?
Nguyên liệu thứ hai là thời gian, nhưng không phải kiểu "14 giờ 05 phút" mà là Unix time: số giây đã trôi qua kể từ 0 giờ ngày 1/1/1970 theo giờ UTC. Mọi máy tính, điện thoại đều dùng con số này bên trong, bất kể bạn đang ở múi giờ nào.

TOTP lấy Unix time chia cho 30 rồi bỏ phần lẻ. Kết quả là số thứ tự của khung 30 giây hiện tại, gọi là T:
| Unix time (giây) | Chia 30, bỏ phần lẻ | Ý nghĩa |
|---|---|---|
| 1.700.000.000 | 56.666.666 | Khung thứ 56.666.666 |
| 1.700.000.015 | 56.666.667 | Đã sang khung mới |
| 1.700.000.040 | 56.666.668 | Lại sang khung mới |
Mọi thiết bị trên thế giới có đồng hồ đúng đều đang ở cùng một số T vào cùng một thời điểm. Đó là lý do điện thoại của bạn và server ở một lục địa khác vẫn "đồng bộ" mà không cần nói chuyện với nhau: cả hai cùng nhìn vào một chiếc đồng hồ chung của nhân loại.
Từ khoá bí mật và thời gian ra 6 chữ số: bên trong HMAC
Có khoá K và số khung T rồi, ứng dụng trộn chúng lại bằng HMAC-SHA1 (mã xác thực thông điệp dùng hàm băm). Bạn có thể hình dung HMAC như một chiếc máy xay sinh tố một chiều: cho khoá và số T vào, nó xay ra một hỗn hợp 20 byte. Biết hỗn hợp thì không thể tách ngược ra nguyên liệu, và chỉ cần đổi một chút nguyên liệu là hỗn hợp khác hoàn toàn.

Quy trình đầy đủ gồm bốn bước:
- Đóng gói T thành 8 byte.
- Tính HMAC-SHA1(K, T), được chuỗi 20 byte trông như ngẫu nhiên.
- Cắt động (dynamic truncation): lấy 4 bit cuối của byte cuối cùng làm vị trí, từ vị trí đó cắt ra 4 byte liền nhau, bỏ bit đầu tiên để thành số nguyên dương 31 bit (tối đa khoảng 2,1 tỷ).
- Lấy 6 chữ số cuối: chia số đó cho 1.000.000 và giữ phần dư. Nếu kết quả ít hơn 6 chữ số thì thêm số 0 phía trước.
Tài liệu RFC 6238 có sẵn bộ số mẫu để kiểm tra. Với khoá thử nghiệm 12345678901234567890 và thời điểm Unix time 59 (tức T = 1), thuật toán SHA1 cho ra mã 8 chữ số 94287082, cắt còn 6 chữ số là 287082. Bạn có thể tự kiểm chứng trên máy có cài oathtool:
# Tính mã TOTP cho một khoá Base32 ngay tại máy, không cần mạng
oathtool --totp -b JBSWY3DPEHPK3PXP
Sáu chữ số cho 1.000.000 tổ hợp. Đoán mò một lần thì xác suất trúng chỉ 1 phần triệu, và server tử tế sẽ khoá tài khoản sau vài lần sai liên tiếp. Đủ an toàn mà người dùng vẫn gõ được trong vài giây.
Vì sao mất mạng vẫn chạy, và server kiểm tra thế nào?
Nhìn lại cả quy trình, bạn sẽ thấy không bước nào cần Internet: khoá đã lưu sẵn trong máy, đồng hồ chạy bằng thạch anh bên trong điện thoại, HMAC chỉ là phép tính của CPU. Bật chế độ máy bay chỉ tắt sóng radio, không đụng gì đến ba thứ này.

Phía server làm y hệt: lấy bản khoá của bạn trong cơ sở dữ liệu, lấy giờ của server, chạy đúng công thức đó. Khi bạn gõ sáu số vào ô đăng nhập, server chỉ việc so khớp hai kết quả. Trùng là cho qua, lệch là từ chối. Hai bên tính độc lập, không bên nào gửi mã cho bên nào.
Một điểm ít người biết: mã TOTP theo chuẩn chỉ được dùng một lần. RFC 6238 yêu cầu server từ chối nếu cùng một mã bị gửi lại lần thứ hai, để kẻ đứng giữa chụp được mã cũng không đem đi dùng lại được.
| Mã qua SMS | Mã TOTP (Authenticator) | |
|---|---|---|
| Cần sóng/mạng khi nhận mã | Có | Không |
| Ai tạo mã | Server, gửi qua nhà mạng | Điện thoại tự tính |
| Rủi ro tráo SIM | Có | Không |
| Bị chặn tin nhắn | Có thể | Không có tin nhắn để chặn |
Khi đồng hồ điện thoại bị lệch thì sao?
Vì cả hệ thống dựa vào việc hai bên cùng ở một khung T, đồng hồ chính là điểm yếu duy nhất. Nếu giờ trên điện thoại lệch vài phút, ứng dụng sẽ tính mã của một khung khác và server báo sai.

Để bù sai số nhỏ (và cả vài giây bạn mất để gõ mã), RFC 6238 khuyến nghị server chấp nhận thêm một khung trước hoặc sau, tức cửa sổ dung sai khoảng 30 giây mỗi bên. Lệch quá mức đó thì chịu.
Thường thì bạn không phải lo, vì điện thoại tự đồng bộ giờ với nhà mạng hoặc máy chủ thời gian mỗi khi có kết nối. Rắc rối chỉ xảy ra khi bạn tắt "giờ tự động" rồi chỉnh tay.
- [ ]Vào cài đặt điện thoại, bật lại Ngày và giờ tự động.
- [ ]Trên Android, Google Authenticator có mục Sửa lỗi thời gian cho mã trong phần cài đặt của ứng dụng, dùng để căn lại giờ (bước này mới cần mạng).
- [ ]Thử lại với mã mới, đừng gõ mã sắp hết hạn.
TOTP an toàn đến đâu?
Mỗi mã chỉ sống 30 giây và chỉ dùng được một lần, nên kẻ gian nhìn trộm qua vai bạn cũng gần như vô dụng. Từ sáu chữ số, cũng không thể suy ngược ra khoá bí mật vì HMAC là hàm một chiều. So với mật khẩu đơn thuần hay mã SMS, đây là một bước nâng cấp lớn.
Nhưng TOTP không chống được lừa đảo thời gian thực. Nếu bạn bấm vào trang đăng nhập giả trông y hệt thật, gõ mật khẩu và cả mã sáu số, kẻ gian có thể chuyển tiếp ngay lập tức sang trang thật trong vòng 30 giây đó. Ứng dụng không hề biết bạn đang gõ mã vào trang nào.

Đó là lý do các tài khoản quan trọng ngày càng chuyển sang khoá bảo mật FIDO2 hoặc passkey: chúng ràng buộc với đúng tên miền thật, nên trang giả không lấy được gì. Thứ tự an toàn có thể tóm gọn: passkey/khoá phần cứng > ứng dụng TOTP > SMS > chỉ có mật khẩu.
TOTP không làm bạn bất khả xâm phạm, nhưng nó biến việc lấy được mật khẩu của bạn từ "đủ để vào" thành "chưa đủ".
Vậy nó có kết nối với server của bạn không?
Khi tạo mã: không. Không với server của Google, cũng không với website bạn đang đăng nhập. Bạn có thể kiểm chứng bằng cách bật chế độ máy bay rồi dùng thử.
Ngoại lệ là khi bạn đăng nhập tài khoản Google trong ứng dụng để đồng bộ, tính năng Google bổ sung từ tháng 4 năm 2023. Lúc đó, các khoá bí mật được sao lưu lên đám mây để bạn đổi điện thoại không mất mã. Tiện, nhưng cũng có nghĩa khoá giờ nằm ở hai nơi, và bảo mật của toàn bộ mã 2FA phụ thuộc vào bảo mật tài khoản Google của bạn. Ngay khi ra mắt, một số nhà nghiên cứu bảo mật đã chỉ ra dữ liệu đồng bộ chưa được mã hoá đầu-cuối. Nếu bạn ngại điều đó, có thể dùng ứng dụng mà không đăng nhập, và chuyển khoá sang máy mới bằng tính năng xuất mã QR.

Rủi ro thực tế lớn nhất không phải hacker mà là mất hoặc hỏng điện thoại. Không có bản sao lưu, bạn có thể tự khoá mình ngoài chính tài khoản của mình. Một vài thói quen nên có:
- Cất mã dự phòng (backup codes) mà website đưa lúc bật 2FA, in ra giấy hoặc lưu trong trình quản lý mật khẩu.
- Bật đồng bộ hoặc xuất khoá sang thiết bị thứ hai trước khi đổi máy, reset máy.
- Thêm phương thức khôi phục thứ hai cho tài khoản quan trọng: khoá phần cứng, số điện thoại dự phòng.
Tóm tắt nhanh
- Google Authenticator dùng chuẩn mở TOTP (RFC 6238): mã = HMAC(khoá bí mật, khung 30 giây hiện tại), cắt còn 6 chữ số.
- Khoá bí mật chỉ trao đổi một lần qua mã QR; sau đó điện thoại và server tính mã độc lập.
- Tạo mã không cần mạng và không gọi về server nào; chỉ cần khoá đã lưu và đồng hồ đúng.
- Đồng hồ lệch quá khoảng 30 giây là mã báo sai; bật giờ tự động để tránh.
- TOTP an toàn hơn SMS nhưng không chống được trang lừa đảo thời gian thực; luôn cất mã dự phòng.
Câu hỏi thường gặp
Xoá ứng dụng Google Authenticator thì có mất mã không?
Có, nếu bạn chưa bật đồng bộ hay xuất khoá. Khoá bí mật chỉ nằm trong ứng dụng, xoá đi là mất. Khi đó bạn phải dùng mã dự phòng hoặc quy trình khôi phục của từng website.
Chuyển sang điện thoại mới thì làm thế nào?
Dùng tính năng chuyển tài khoản (xuất mã QR) trong ứng dụng để quét từ máy mới, hoặc đăng nhập cùng tài khoản Google nếu đã bật đồng bộ. Kiểm tra máy mới tạo mã đúng rồi mới xoá ở máy cũ.
Vì sao hai ứng dụng khác nhau cho ra cùng một mã?
Vì chúng cùng cài đặt chuẩn TOTP. Cùng khoá, cùng thời điểm, cùng công thức thì bắt buộc ra cùng kết quả, bất kể ứng dụng nào.
Đổi múi giờ khi đi du lịch có làm mã sai không?
Không. TOTP dùng Unix time tính theo UTC, không phụ thuộc múi giờ. Chỉ cần đồng hồ của máy chạy đúng, đổi múi giờ thoải mái.



