兩步驗證
大家應該對兩步驗證都熟悉吧?如蘋果有內建的兩步驗證策略,防止使用者帳號密碼被盜而鎖定手機進行敲詐,這種例子屢見不鮮,所以蘋果都建議大家開啟兩步驗證的。
Google 的身分識別驗證器一般也是用於登入進行兩步驗證,和蘋果的兩步驗證是同樣的道理。只不過 Google 的身分識別驗證器用得更多更廣泛,如 GitHub 的兩步驗證都是基於 Google 身分識別驗證器。
Google Authenticator 簡介
Google Authenticator 身分識別驗證器是一款基於時間與雜湊的單次密碼演算法的兩步驗證軟體令牌,使用者需要下載手機 APP(Authenticator),該手機 APP 與網站進行綁定,當網站驗證完使用者名稱和密碼之後會驗證此 APP 上對應產生的 6 位驗證碼數字,驗證通過則成功登入,否則登入失敗。
Google Authenticator 使用
我們來看下 Github 上的使用 Google 身分識別驗證器開啟兩步驗證的應用。
,預設 Github 是沒有開啟兩步驗證的,點擊設定按鈕進行設定。
Github 提供了基於 APP (Google身分識別驗證器)和簡訊驗證碼兩種兩步驗證的方式,我們選擇第一種Google身分識別驗證器。
進入第一種驗證模式,接下來展示了一堆的恢複碼,用來當 APP 驗證器不能工作的緊急情況使用。把它們儲存起來,然後點擊下一步。
這個就是身分識別驗證器的關鍵了,下載 Google 的 Authenticator
APP,然後掃描這個二維碼進行綁定。
綁定之後,APP Github 模組下面會顯示一個 6 位的驗證碼,把它輸入到上面那個框裡面就行了。
如所示,已經成功開啟兩步驗證了。
接下來我們退出 Github 再重新登入,頁面就會提示要輸入 Google 的身分識別驗證器驗證碼了,如果 APP 不能正常工作,最下方還能通過之前儲存下來的恢複碼進行登入。
好了,Google Authenticator 使用就到這裡,那它是如何工作的,它是什麼原理呢?我們的網站、APP 如何接入 Google Authenticator,接下來我們一一拉開謎底。
Google Authenticator 工作流程
實際上 Google Authenticator 採用的是 TOTP 演算法(Time-Based One-Time Password,即限時單次密碼),其核心內容包括以下三點。
1、安全密鑰
是用戶端和服務端約定的安全密鑰,也是手機端 APP 身分識別驗證器綁定(手機端通過掃描或者手輸安全密鑰進行綁定)和驗證碼的驗證都需要的一個唯一的安全密鑰,該密鑰由密碼編譯演算法產生,並最後由 Base32 編碼而成。
2、驗證時間
Google 選擇了 30 秒作為時間片,T的數值為 從Unix epoch(1970年1月1日 00:00:00)來經曆的 30 秒的個數,所以在 Google Authenticator 中我們可以看見驗證碼每個 30 秒就會重新整理一次。
更詳細原理參考:
blog.seetee.me/post/2011/google-two-step-verification/
3、簽署演算法
Google 使用的是 HMAC-SHA1 演算法,全稱是:Hash-based message authentication code(雜湊運算訊息認證碼),它是以一個密鑰和一個訊息為輸入,產生一個訊息摘要作為輸出,這裡以 SHA1 演算法作為訊息輸入。
使用 HMAC 演算法是因為只有使用者本身知道正確的輸入密鑰,因此會得到唯一的輸出,其演算法可以簡單表示為:
hmac = SHA1(secret + SHA1(secret + input))
事實上,TOTP 是 HMAC-OTP(基於HMAC的一次密碼產生)的超集,區別是 TOTP 是以目前時間作為輸入,而HMAC-OTP 則是以自增計算機作為輸入,該計數器使用時需要進行同步。
Google Authenticator 實戰
知道上面的原理,我們就可以來應用實戰了。
/** * 公眾號:Java技術棧 */public class AuthTest { @Test public void genSecretTest() { String secret = GoogleAuthenticator.generateSecretKey(); String qrcode = GoogleAuthenticator.getQRBarcodeURL("Java技術棧", "javastack.cn", secret); System.out.println("二維碼地址:" + qrcode); System.out.println("密鑰:" + secret); } @Test public void verifyTest() { String secret = "ZJTAQGLVOZ7ATWH2"; long code = 956235; GoogleAuthenticator ga = new GoogleAuthenticator(); boolean r = ga.verifCode(secret, code); System.out.println("是否正確:" + r); }}
第一個方法是產生密鑰和一個掃描二維碼綁定的URL。
第二個方法是根據密鑰和驗證碼進行驗證。
這裡僅提供一下 GoogleAuthenticator 類的源碼邏輯參考。
http://awtqty-zhang.iteye.com/blog/1986275
如果有收穫歡迎點贊轉寄,也可以留言發表你的疑問和看法。
教程:史上最強 Spring Boot & Cloud 教程匯總
工具:推薦一款線上創作流程圖、思維導圖軟體