原文英文版本刊於:What is TOTP? A short guide for developers (RFC 6238 explained) - Authgear Blog
TOTP(Time-based One-Time Password,時間型一次性密碼)是一種簡單、廣泛使用的驗證方式,透過「共享密鑰」加上「目前時間」來產生短效的數字驗證碼(依據 RFC 6238 標準)。最常見的形式是 6 位數密碼,每 30 秒更新一次。
這份指南會帶你了解 TOTP 的運作原理、常見的錯誤點,並附上 Node、Python、Go 的快速程式碼範例。你也可以直接試用我們的 線上 TOTP 產生器。
什麼是TOTP?
TOTP 全名是 Time-based One-Time Password(時間型一次性密碼)。它透過一組「共享密鑰」(通常是 Base32 格式的字串)再加上「當下的時間」,產生一組會很快失效的短數字驗證碼,最常見的是 每 30 秒更新一次。
TOTP 是由 IETF 的 RFC 6238 標準化所訂定,也是大部分驗證器 App(像是 Google Authenticator、Authy、Authgear TOTP 產生器等)的運作機制。
TOTP 運作原理
- 共享密鑰:
Server 和 Authenticator 在設定 2FA 時會約定一組密鑰(通常是 Base32 格式)。 - 時間步長(timestep):
用當下 Unix 時間除以週期(常見 30 秒),得到一個遞增計數器。 - HMAC:
雙方用密鑰 + 計數器跑 HMAC(SHA-1/256/512)。 - 截斷(Truncation):
動態擷取出固定長度的數字碼(多數是 6 位)。 - 驗證:
Server 計算預期的 TOTP,並檢查使用者輸入是否符合(通常允許 ±1 step 容錯)。
演算法
TOTP = Truncate(HMAC(secret, floor(currentTime / timestep))) % 10^digits
參數
- 密鑰格式:Base32(例:JBSWY3DPEHPK3PXP)
- 有效時間:30 秒(RFC 6238 推薦值)
- 字數:6 位最常見,8 位更安全但較難輸入
- 演算法:SHA-1 最廣泛支援,也可用 SHA-256/512
程式碼範例
Node (otplib)
// npm i otplib
const { totp } = require('otplib');
totp.options = { algorithm: 'sha1', digits: 6, step: 30 };
const secret = 'SECRET_BASE32';
const code = totp.generate(secret);
console.log('TOTP:', code);
// Verify:
const valid = totp.check(code, secret);
console.log('valid:', valid);
Go (pquerna/otp)
import (
"fmt"
"time"
"github.com/pquerna/otp/totp"
)
func main() {
secret := "SECRET_BASE32"
code, _ := totp.GenerateCode(secret, time.Now())
fmt.Println("TOTP:", code)
valid := totp.Validate(code, secret)
fmt.Println("valid:", valid)
}
常見陷阱與除錯方式
- 時鐘偏移:TOTP 仰賴準確時間。如果驗證碼「對不起來」,請同步 Server 與 Authenticator 的時鐘(使用 NTP),或在驗證時允許 ±1 step 的時間容差。
- 密鑰格式錯誤:請確認密鑰是 Base32 格式,並移除空白字元。如果拿到的是 QR code(otpauth:// URL),要從其中解析出
secret=
的參數。 - 演算法 / 位數不一致:Server 與 Client 必須使用相同的演算法(SHA-1/256/512)與位數(6 或 8 位)。這類不一致是最常見的錯誤來源。
- 誤用正式環境的密鑰:不要把正式環境的金鑰放在公開或線上工具裡。請使用本機 / 離線產生器,或測試環境的密鑰來除錯。
安全注意事項
- TOTP 是您所擁有的驗證器,可以有效抵擋遠端純密碼攻擊,但若共用金鑰被盜就失效。
- 請搭配其他安全措施:例如速率限制、異常偵測來結合使用。
- 若可以能同時控制客戶和服務端,建議改用 SHA-256/512,加強 HMAC 強度。
何時使用 TOTP
- 適合:人工登入、管理者後台、開發測試流程、內部工具
- 不適合:高風險無人管控的 API 訪問 (使用用戶端憑證、OAuth token 或硬體支援的金鑰來獲得更強的保護)
- 使用其他MFA方案:Push MFA、FIDO2 / WebAuthn(Passkeys)、硬體 Token
如何進行整合測試
- 從 provisioning 流程抽出共享 secret(Base32)。
- 用上面程式碼在本地產生 TOTP。
- Server 驗證時要允許 ±1 step 容錯。
- 刻意測試錯誤參數(演算法、位數)以確認 Log 能正確記錄。
- 用測試工具預覽驗證碼:👉 Authgear TOTP Authenticator
FAQ
Q: TOTP 的標準時間週期是多少?
A: 30 秒(RFC 6238 的建議值)。
Q: 幾位數比較好?
A: 6 位數最常用,8 位數安全性更高,但輸入體驗較差。
Q: TOTP 安全嗎?
A: 只要密鑰妥善保管,並搭配其他控管措施(例如速率限制、裝置綁定),OTP 可以抵擋多數攻擊。若需要更高安全性,建議在合適的情境下改用 FIDO2 / Passkeys。