TOTP:Time-Based One-Time Password Algorithm,基於時間同步的一次性口令,動態口令html
技術標準:https://tools.ietf.org/html/rfc6238算法
參考連接:數據庫
https://blog.csdn.net/LVXIANGAN/article/details/73775969安全
https://www.cnblogs.com/loveyou/p/6989064.html服務器
使用阿里雲身份寶(或者Google Authenticator)時間同步實現OTP動態口令dom
如上圖,是一種基於時間同步的OTP計算方式,是經過客戶端和服務器持有相同的密鑰並基於時間基數,服務端和客戶端採用相同的Hash算法,計算出長度爲六位的校驗碼。當客戶端和服務端計算出的校驗碼相同是,那麼驗證經過。阿里雲
因爲客戶端須要存儲密鑰和計算校驗碼的載體,阿里雲的身份寶(或者Google 的Authenticator)提供了手機端的APP進行密鑰存儲和校驗碼計算。下面咱們以這兩款客戶端爲例,實如今應用採用OTP進行權限驗證,主要流程以下圖:.net
【生成密鑰】code
String secretBase32 = TotpUtil.getRandomSecretBase32(64);htm
oper.setOtpSk(secretBase32);
【構造掃碼字符串】
格式:otpauth://totp/[客戶端顯示的帳戶信息]?secret=[secretBase32]
String totpProtocalString = TotpUtil.generateTotpString(operCode, username, secretBase32);
【生成二維碼】
QRUtil.generateMatrixPic(totpProtocalString, 150, 150, filePath, fileName);
【生成動態口令】
secretHex = HexEncoding.encode(Base32String.decode(secretBase32))
long timeStep = 30L; // 動態口令有效性持續的時間區間 30s
steps = Long.toHexString(System.currentTimeMillis() / 1000L / timeStep).toUpperCase();
steps = "000000000000".substring(0, 16-steps.length())+steps;
generateTOTP(secretHex, steps, "6", "HmacSHA1");
=========================================================================================
顯然驗證的時候要求客戶端和服務端時間上基本同步,兩者相差應該在 timeStep 之內,不然客戶端和服務端計算獲得的動態口令就不一致。
這一特性使得用戶必須在 timeStep 時間內獲取並輸入、提交動態口令。從算法看可以成功驗證的時間區間在時間軸上是長度爲 timeStep 先後排列、緊密鏈接的時間窗口。一旦用戶獲取動態口令的時間和服務端驗證動態口令的時間不在同一個時間區域內,驗證將失敗。
若是把時間窗的大小 timeStep 設置大一點,能夠下降正常驗證中因錯開時間窗致使失敗的機率。但這又引入另一個問題:若是用戶某次使用的動態口令被泄露,那麼在必定時間內被泄露的動態口令還能夠成功地被用來作身份驗證。
① 爲提高用戶體驗同時保證安全性,此處對驗證環節作一些調整:
數據庫中除了存儲用戶信息和密鑰以外,創建一張表用於存儲和管理近期的動態口令。
假設約定動態口令的有效期爲2分鐘,每 timeStep=30 秒生成新的動態口令。那麼從 t0 開始存入第 1 個動態口令,t0+30s 後存入第 2 個動態口令,t0+60s 後存入第3個動態口令, t0+90s 後存入第4個動態口令,t0+120s 後刪除 t0 對應的動態口令,插入第 5 個動態口令,以此類推,數據庫中老是存有 1~4 個有效的動態口令。當服務端收到一次動態口令認證請求時,只要傳入的口令與數據庫中存儲的該用戶對應的任意一個動態口令相同,那麼驗證成功,並刪除數據庫中相應的口令記錄(表示已經使用過,宣佈失效)。
這樣只要用戶在提交驗證請求前 90秒內獲取動態口令那麼驗證確定是成功的。若是是提交驗證請求前 90~120秒 獲取的動態口令,那麼可能驗證成功,也可能失敗。
② 動態口令的另外一種使用方式:消息下發
消息下發的形式最多見的就是短信、郵件、IM。
服務端根據用戶信息、時間和密鑰生成並臨時存儲動態口令,而後將口令發送給用戶,在約定的時間內用戶提交收到的動態口令,服務端在比對後斷定驗證結果。
③ 事件驅動的動態口令生成和傳遞機制:
如上所述,若是服務器每隔 timeStep 時間就得更新一下數據庫裏全部用戶的動態口令,因爲動態口令只有在用戶登陸認證的時候纔會使用,那麼勢必帶來計算浪費。
一個變通的實踐方法是:
當服務端收到認證請求時即時生成4個動態口令,這4個口令分別對應當前時間 t0、t0-30s、t0-60s、t0-90s 四個時間點對應的動態口令。
查找驗證歷史記錄表,找出相應用戶在時間大於 t0-90s 的範圍內的驗證成功的記錄,在4個動態口令中去除已經驗證過的口令。
而後將用戶提交的口令與最近的 0~4 個有效口令進行比對,若是無一匹配那麼驗證失敗;若是有一個匹配那麼驗證成功,並將對應的驗證事件(用戶,動態口令,驗證結果,時間)存入數據庫。
考慮認證服務和安全監控的需求,能夠將每次認證(不論成功、失敗,或用戶提交了已經使用過的動態口令)事件都記錄下來,用於幫用戶分析認證失敗的緣由,以及監控動態口令可能被劫持盜用等行爲。