Tạo Mã TOTP / 2FA

Trình tạo mã TOTP / 2FA miễn phí (RFC 6238). Dán secret Base32 để xem mã hiện tại và mã kế tiếp, quét QR bằng Google Authenticator, kiểm tra cấu hình 2FA.

000 000
--s
Mã kế tiếp:
Tài Khoản & Thuật Toán
Dán secret mã hoá Base32. Ký tự A–Z và chữ số 2–7, padding tuỳ chọn. Nhấn biểu tượng xúc xắc để tạo secret 20 byte ngẫu nhiên.
Quét bằng Authenticator

Trình Tạo Mã TOTP / 2FA (RFC 6238)

Tạo Time-based One-Time Password (TOTP) hoàn toàn trên trình duyệt. Dán bất kỳ secret Base32 nào — loại mà Google Authenticator, Authy, Microsoft Authenticator, 1Password đều import được — và xem ngay mã 6 chữ số trực tiếp, mã kế tiếp, vòng đếm ngược, URI otpauth:// và mã QR có thể quét bằng mọi ứng dụng authenticator. Triển khai đúng RFC 6238, đã đối chiếu với cả sáu test vector chính thức. Hữu ích để debug cấu hình 2FA, kiểm chứng phát mã phía server, hoặc làm authenticator hoàn toàn offline.

TOTP là gì, khác HOTP thế nào?

TOTP (Time-based One-Time Password, RFC 6238) tạo mã 6–8 chữ số đổi mỗi 30 giây. Đây là thuật toán đứng sau Google Authenticator, Microsoft Authenticator, Authy, OTP tích hợp của 1Password, FreeOTP và hàng chục ứng dụng khác.

Nó dựng trên HOTP (HMAC-based One-Time Password, RFC 4226):
- HOTP dùng bộ đếm tăng 1 mỗi lần bạn bấm nút hoặc sử dụng mã.
- TOTP dùng thời gian Unix hiện tại chia cho chu kỳ (mặc định 30s) làm bộ đếm. Tại T = floor(time / 30), giá trị mã giống nhau với mọi người dùng có cùng secret.

Cả hai tạo mã bằng cách tính HMAC(secret, counter) rồi cắt ngắn. TOTP thực tiễn hơn vì không cần đồng bộ giữa client và server ngoài việc cả hai có đồng hồ đủ chính xác (cấp NTP là đủ).

Công cụ này thực sự tính gì?

Đúng những gì RFC 6238 quy định — đã đối chiếu với test vector chính thức ở Phụ lục B:

1. Giải mã secret Base32 thành byte thô.
2. Tính counter = floor(unix_time / period) và đóng gói thành 8 byte big-endian.
3. Tính HMAC trên 8 byte đó bằng thuật toán đã chọn (SHA-1, SHA-256 hoặc SHA-512) và secret.
4. Cắt động (dynamic truncation): lấy 4 bit cuối của HMAC làm offset, đọc 4 byte bắt đầu từ offset đó, che bit cao nhất.
5. Xuất (bin % 10^digits), thêm số 0 đầu cho đủ độ rộng.

Bước HMAC dùng Web Crypto SubtleCrypto của trình duyệt nên phần mật mã là native và đã được kiểm toán; công cụ này chỉ ráp giao thức quanh nó. Sáu test vector RFC (T = 59, 1111111109, 1111111111, 1234567890, 2000000000, 20000000000) đều khớp kết quả mong đợi.

Làm sao thêm tài khoản mới vào Google Authenticator bằng công cụ này?

Hai luồng, tuỳ phía bạn kiểm soát:

1. Bạn có dịch vụ tạo ra secret (hiện chuỗi hoặc QR). Dán secret Base32 vào ô Secret, tuỳ chọn điền 'Nhãn tài khoản' (vd [email protected]) và 'Đơn vị phát hành' (tên dịch vụ) để authenticator hiển thị nhãn rõ ràng. Công cụ sẽ hiện mã hiện tại để bạn so với bước xác minh của dịch vụ.

2. Bạn đang xây dịch vụ và cần enroll người dùng. Nhấn xúc xắc để tạo secret Base32 ngẫu nhiên 20 byte, điền 'Nhãn tài khoản' và 'Đơn vị phát hành'. QR mã hoá URI otpauth:// tiêu chuẩn — người dùng quét trên ứng dụng authenticator và bắt đầu sinh mã khớp ngay lập tức. Sao chép URI otpauth:// để nhúng vào QR của bạn, hoặc tải PNG QR đã render.

Ở cả hai luồng, mã được tạo cục bộ — không bao giờ truyền đi — nên an toàn cả với secret production.

Có an toàn không khi dán secret 2FA thật ở đây?

Về kỹ thuật là có — mọi thứ chạy trên trình duyệt — nhưng secret TOTP Base32 là 'thẻ chủ' của 2FA. Ai biết nó cũng tạo được cùng mã như bạn. Hãy đối xử như mật khẩu:

- Đừng dán ở trình duyệt không tin cậy (kiosk, máy dùng chung, trình duyệt cài extension không tin cậy).
- Mở DevTools → Network để kiểm chứng secret không bao giờ bị POST. Đúng là không — nhưng quyền kiểm chứng nằm ngay ở đó.
- Đừng để trang mở trong tab mà người khác đọc được giá trị.
- Với đa số người dùng, lý do hợp lý để dùng công cụ này là test hoặc phục hồi từ backup (vd bạn lưu secret từ màn cài đặt của dịch vụ và mất app authenticator); không phải để thay khoá phần cứng hằng ngày.

Nếu bạn dùng nút xúc xắc để tạo secret ngẫu nhiên, secret test đó chia sẻ thoải mái — nhưng bất kỳ secret nào gắn với tài khoản thật thì phải bảo vệ như mật khẩu.

Định dạng URI otpauth:// như thế nào?

URI chuẩn theo RFC, dùng bởi mọi ứng dụng authenticator lớn:

otpauth://totp/Issuer:[email protected]?secret=BASE32SECRET&issuer=Issuer&algorithm=SHA1&digits=6&period=30

Các trường:
- 'Path' sau totp/ là label, thường là 'Issuer:Account'. Tiền tố Issuer là tuỳ chọn nhưng được khuyến nghị; cả hai chỗ nên khớp tham số issuer.
- secret: Base32, không padding, ưu tiên chữ hoa.
- issuer: tên dịch vụ dễ đọc (URL-encode).
- algorithm: SHA1 (mặc định), SHA256, hoặc SHA512. Nhiều app chỉ hỗ trợ SHA1.
- digits: 6 (mặc định), 7, hoặc 8. Nhiều app chỉ hỗ trợ 6.
- period: 30 (mặc định) giây. Một số app cho phép 60.

Công cụ chỉ thêm tham số khác mặc định để URI gọn nhẹ. Authenticator chấp nhận tham số dư nhưng dạng bỏ mặc định là khả chuyển nhất.

Vì sao mã trên app authenticator đôi khi lệch một bước?

TOTP phụ thuộc cả hai đầu có đồng hồ đủ gần. Nếu đồng hồ thiết bị lệch quá vài giây, mã bạn tạo sẽ tính trên time-step khác với server.

Cách dịch vụ và client xử lý:

- Server thường chấp nhận cả mã trước và mã sau ngoài mã hiện tại. Như vậy có cửa sổ ~±30 s.
- Client nên chạy NTP. Trên Android, bật 'Use network-provided time'; iOS bật 'Set Automatically' trong Date & Time; Linux/macOS dùng systemd-timesyncd hoặc chrony để đồng bộ trong vài mili giây với server NTP.
- Authy và Google Authenticator đều có nút 'sync time' trong app để lấy giờ mạng mà không đổi đồng hồ hệ thống.

Công cụ này dùng đồng hồ hệ thống cục bộ (Date.now() từ trình duyệt). Nếu cả hai đồng hồ đúng, mã khớp; nếu một bên lệch quá 60 s, bạn sẽ thấy không khớp.

Nên chọn thuật toán và số chữ số nào?

Mặc định là SHA-1, 6 chữ số, chu kỳ 30 s. Lý do cân nhắc đổi:

- SHA-1: mặc định phổ quát. Mọi authenticator hỗ trợ. Khuyến nghị trừ khi có lý do cụ thể.
- SHA-256 / SHA-512: HMAC mạnh hơn. Hữu ích khi cả server phát hành và app client hỗ trợ (Authy và 1Password có; một số phiên bản Google Authenticator cũ không render đúng SHA-256+).
- 6 chữ số: được hỗ trợ phổ biến, xác suất đoán đúng ~1 phần triệu mỗi lần.
- 7 / 8 chữ số: mạnh hơn; Yubico OATH hỗ trợ; nhiều app chỉ hiện 6.
- Chu kỳ 30 s: chuẩn. 60 s giảm tốc độ sinh mã mới và dễ chống replay phía server; 15 s hiếm và phá vỡ một số app.

Để tương thích, hãy dùng SHA-1 / 6 / 30. Với công cụ nội bộ tự kiểm soát cả hai phía, SHA-256 / 6 / 30 là nâng cấp hợp lý.

Dữ liệu đi đâu? Có dùng offline được không?

Secret không rời trình duyệt. Bộ sinh chạy hoàn toàn phía client:

- HMAC được tính qua window.crypto.subtle, chính nguyên thuỷ HTTPS dùng. Không bundle bất kỳ triển khai SHA-1 JS nào.
- Phần render QR dùng thư viện qrcode tải một lần từ CDN công cộng (cdn.jsdelivr.net). Sau lần tải đó, trang hoạt động offline — bao gồm sinh mã. Tắt Wi-Fi và xem nó vẫn chạy.
- Không phân tích gì trên dữ liệu nhập. Bạn kiểm chứng bằng DevTools → Network khi gõ; chỉ có request tài nguyên tĩnh.
- Nút 'Sao chép mã' và 'Sao chép URI' ghi vào clipboard cục bộ. Nút 'Tải QR' tạo PNG trong bộ nhớ và mở hộp thoại lưu cục bộ.

Để dùng offline tối đa, tải trang một lần trên máy tin cậy rồi ngắt mạng. HMAC, decode base32, render QR và clipboard tiếp tục chạy — hữu ích cho cấu hình server cô lập (air-gapped) hoặc kịch bản phục hồi.

Tính Năng Nổi Bật

  • Tuân thủ RFC 6238, đã kiểm chứng cả sáu test vector chính thức
  • HMAC qua Web Crypto API native của trình duyệt (không bundle crypto JS)
  • Hỗ trợ SHA-1, SHA-256 và SHA-512
  • Số chữ số tuỳ chỉnh (6 / 7 / 8) và chu kỳ (15 / 30 / 60 giây)
  • Hiển thị cập nhật trực tiếp mã hiện tại và mã kế tiếp
  • Vòng đếm ngược động cho biết số giây còn lại của time-step
  • Tạo secret Base32 ngẫu nhiên 20 byte bằng crypto.getRandomValues
  • URI otpauth:// tương thích Google Authenticator, Authy, 1Password, Microsoft Authenticator…
  • Tạo mã QR quét sạch trên mọi app authenticator lớn
  • Nút hiện/ẩn cho ô secret
  • Sao chép mã hoặc URI otpauth chỉ một cú nhấp
  • Tải QR dưới dạng ảnh PNG
  • Trường nhãn tài khoản và issuer cho mục authenticator dễ đọc
  • 100% phía client — secret không rời trình duyệt
  • Hoạt động offline sau lần tải đầu