短信驗證的設(shè)計
在業(yè)務(wù)中,為安全起見,常常需要二次驗證。其流程一般為,密碼驗證之后,需要再次輸入一個一次性的密碼(一般為位數(shù)較短的數(shù)字),才能完成驗證。二次驗證一般需要同時驗證設(shè)備的***性。
從驗證方式上看,二次驗證可以通過短信驗證或 APP 驗證(Google Authenticator)。對于短信驗證,優(yōu)點是操作方便,不需安裝額外的 APP;缺點是實時性較差,依賴短信,有被竊聽的風(fēng)險。APP 方式正好相反。
google authenticator
以此來看,在業(yè)務(wù)初期,宜使用短信驗證方式,減少用戶輸入的復(fù)雜度。待用戶量和用戶黏度上去之后可以考慮換用 APP 驗證。畢竟,在已經(jīng)安裝 APP 的情況下,這種方式更加便捷和安全。
OTP(one time password),即一次性驗證密碼,也稱動態(tài)口令。一次性密碼的產(chǎn)生方式,主要是以時間差做為服務(wù)器與密碼產(chǎn)生器的同步條件。在需要登錄的時候,就利用密碼產(chǎn)生器產(chǎn)生一次性密碼,OTP 一般分為計次使用(HOTP)以及計時使用(TOTP)兩種,計次使用的 OTP 產(chǎn)出后,可在不限時間內(nèi)使用;計時使用的 OTP 則可設(shè)定密碼有效時間,從 30 秒到兩分鐘不等,而 OTP 在進行認(rèn)證之后即廢棄不用,下次認(rèn)證必須使用新的密碼,增加了試圖不經(jīng)授權(quán)存取有限制資源的難度1。
Google Authenticator 的二次驗證也是使用的 OTP。其核心原理是:服務(wù)器和客戶端(一般是Google Authenticatorapp)保存同一份密鑰,客戶端根據(jù)該密鑰和當(dāng)前時間戳計算得到 6 位數(shù)字,發(fā)到服務(wù)器,服務(wù)器根據(jù)同樣的算法得到 6 位數(shù)字。做比較之后判斷客戶端傳來的數(shù)字是否合法。詳述如下2:

Google Authenticator View
對于 HOTP,客戶端和服務(wù)器事先協(xié)商好一個密鑰 K,用于一次性密碼的生成過程,此密鑰不被任何第三方所知道。此外,客戶端和服務(wù)器各有一個計數(shù)器 C,并且事先將計數(shù)值同步。
進行驗證時,客戶端對密鑰和計數(shù)器的組合(K,C)使用 HMAC(Hash-based Message Authentication Code)算法計算一次性密碼,公式如下:
HOTP(K,C)=Truncate(HMAC_SHA1(K,C))
經(jīng)過截斷,得到的 OTP 一般是 6 位數(shù),用戶將得到的 OTP 發(fā)送到服務(wù)器,服務(wù)器端經(jīng)過同樣的驗證,驗證成功則計數(shù)器加 1。
TOTP 將 HOTP 中的計數(shù)器 C 用當(dāng)前時間來替代,于是就得到了隨著時間變化的一次性密碼。也就是說,當(dāng)給定密鑰之后,每一時刻的 OTP 都是固定不變的(假設(shè)間隔時間固定為 T)。
這里需要稍加注意的地方是間隔時間的選擇,不能太長,否則安全性不能保證;也不能太短,否則用戶無法及時驗證。Google 的選擇是 30 秒。當(dāng)我們使用 Google Authenticator 驗證時,因為 OTP 的獲得沒有延遲,因此 30 秒是個比較合理的數(shù)字;如果我們想要通過短信進行驗證,考慮到短信推送的延遲和用戶讀取的延遲,30 秒的時間可能有點短。通常情況下短信驗證的有效時間在 1 分鐘到 2 分鐘之間,這是一個比較合理的數(shù)字。
TOTP 還有個邊界問題,如下圖所示。當(dāng)在 OA 時刻發(fā)起短信驗證請求,在理想情況下,我們只有在 OA 時間段發(fā)起驗證,驗證才能成功。也就是說,用戶的有效輸入時間在 T(當(dāng)發(fā)起時刻靠近 O 時)到 0 之間(當(dāng)發(fā)起時刻靠近 A),也就是說,用戶有一定的概率驗證幾乎必然失敗(發(fā)起時刻靠近 A,考慮到 OTP 獲取延遲和用戶輸入延遲),這顯然是不合理的。

otp verification
可以通過在驗證時刻驗證當(dāng)前時刻以及前 N 個時間片來解決這個問題。如圖所示,我們驗證當(dāng)前時刻和前一時刻,當(dāng)在 OA 時間片發(fā)起驗證時,驗證區(qū)間是 OB 段,這樣用戶的有效輸入時間就是 T~2T,如果我們?nèi)?T 為 1 分鐘,這會是一個比較合理的結(jié)果。
真實情況下還要考慮客戶端和服務(wù)器的時鐘偏差,不再贅述。(如果使用短信驗證,基本不存在這個問題,因為發(fā)起驗證的 OTP 也是由服務(wù)器產(chǎn)生的。)