源起
最近自己在很多地方的登入都需要2FA驗證,先用手機裝驗證軟體掃QRCode,之後的每次登入都要輸入6位數字, 一直沒搞懂原理,但又覺得很酷,剛好最近要做一個python私人用的密碼管理程式,就在想能不能結合這個東西來驗證, 以下就是自己理解後名詞的介紹
實作的Github
https://github.com/hanksky12/Personal-Password-Manager
MFA(Multi-Factor Authentication)
除了密碼之外,在登入時有其他驗證須通過就可以稱為多重驗證(多因子驗證)
例子:輸入手機收到的簡訊數字、線上銀行ATM提款卡、手機TOTP的六位數字
2FA
MFA的特例,兩種驗證就是2FA,以此類推
OTP(One Time Password)
一次性驗證碼,用完就丟,只能用一次,其中有名的演算法是HOTP和TOTP
HOTP(HMAC-based)
HMAC雜湊訊息驗證碼 RFC4226
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
C 8-byte counter value, the moving factor. This counter
MUST be synchronized between the HOTP generator (client)
and the HOTP validator (server).
K shared secret between client and server; each HOTP
generator has a different and unique secret K.
白話文:
用一串key string 加上 counter計數器,做Hash之後,取特定位數做比對
實作:
產出器將key傳到比對器之後,兩邊各自跑counter計數器,看最後出來的值是否一致
- 兩邊各自跑counter,所以可能有前後落差要處理
- 最後只取特定位數 ,所以要限制比對次數,避免被大量嘗試攻擊
- 重點在key必須隱蔽的傳到對方的比對器,不能外流
TOTP(Time-based)
HOTP的特化版,counter計數器使用timestamp
why 30秒?
必然server跟手機不可能時間永遠同步, 在兩邊跑出來的結果可能有落差,通常使用30秒才換一次, 來容納兩邊的時間不同步,否則驗證失敗可能性太高,server壓力太大,
why 6位數?
6位數,是一百萬組可能性,需在30秒內嘗試完成,每秒要驗證3.3萬次,server後台可以藉此鎖定黑名單
QRCode
用來傳遞key string,所以要確保隱蔽,通常網站讓你掃完就會消失,無法存檔,確保只有你的手機有這個key
python實作套件
import pyotp
#限制base32的key才能使用
_otp = pyotp.TOTP(base32_key)
參考資料
https://en.wikipedia.org/wiki/Time-based_one-time_password
https://medium.com/starbugs/totp-2fa-algorithm-in-10-mins-25acc3c35df9