在多因素驗證(MFA)的世界裡,TOTP 與 HOTP 是兩種最主流的一次性密碼規範。兩者同樣基於 HMAC 雜湊與共享對稱金鑰,卻因動態因子的不同,在安全特性與應用場景上各有取捨。
HOTP:計數器驅動的一次性密碼
HOTP(HMAC-Based OTP,RFC 4226) 以一個遞增計數器作為動態因子。每次產生 OTP,計數器加一;伺服器驗證成功後,同步更新自身計數器。由於不依賴時間,無需裝置與伺服器的時鐘同步,離線環境也能正常運作。然而,若使用者多次產生 OTP 卻未驗證,則客戶端與伺服器計數器將產生失步(Desynchronization)。規範允許伺服器在一定容差窗口(Look-ahead Window)內向前比對,以補救失步問題。此外,已使用的 OTP 若未被伺服器及時消費,存在重放攻擊風險。
TOTP:時間驅動的一次性密碼
TOTP(Time-Based OTP,RFC 6238) 是 HOTP 的延伸,以當前 Unix 時間戳除以時間步長(預設 30 秒)作為計數器。兩端各自獨立計算,毋須通訊即可對齊。時間步長結束後 OTP 自動失效,抗重放攻擊能力顯著優於 HOTP。代價是要求客戶端與伺服器的時鐘誤差不超過一個步長;實務上伺服器通常允許前後各一個窗口的容差(±30 秒)。Google Authenticator、Microsoft Authenticator 等主流應用均採用此規範。
import pyotp
secret = pyotp.random_base32()
totp = pyotp.TOTP(secret) # TOTP(時間驅動)
hotp = pyotp.HOTP(secret) # HOTP(計數器驅動)
print(totp.now()) # 當前 30 秒內有效的 OTP
print(hotp.at(0)) # 計數器為 0 時的 OTP
💡 重點整理:TOTP vs HOTP
- 動態因子:TOTP 用時間步長,HOTP 用遞增計數器。
- 抗重放攻擊:TOTP 的 OTP 30 秒後自動失效,安全性更高。
- 同步需求:TOTP 需時鐘對齊;HOTP 需管理計數器失步問題。
- 適用場景:TOTP 適合互動式登入;HOTP 適合無網路的實體 Token。
大多數現代系統應優先選擇 TOTP,其自動過期機制大幅降低重放風險。若應用場景無法保證時鐘同步,HOTP 仍是可靠的備選方案,但必須妥善設計計數器管理邏輯。
📚 參考文獻
- M'Raihi et al., RFC 4226 – HOTP: An HMAC-Based One-Time Password Algorithm,IETF,2005。https://datatracker.ietf.org/doc/html/rfc4226
- M'Raihi et al., RFC 6238 – TOTP: Time-Based One-Time Password Algorithm,IETF,2011。https://datatracker.ietf.org/doc/html/rfc6238
- PyOTP 官方文件,Python One-Time Password Library。