閱讀本篇文章你能夠了解到谷歌驗證器的實現原理,而且能夠本身使用node.js實現支持谷歌驗證器的兩步驗證。
這兩年發現身邊的不少應用和網站紛紛支持兩步驗證,而且呼籲用戶使用兩步驗證。javascript
而且發現,除了Apple ID的兩步驗證以外,其它兩步驗證不少能看到谷歌驗證器(Google Authenticator)的身影。html
這讓我產生了濃厚的興趣,到底谷歌驗證器的原理是什麼,我本身能實現一個相似的驗證器嗎?java
兩步驗證就是當用戶輸入帳號密碼並驗證成功以後,須要額外輸入一串一次性隨機密碼(通常是4-6位的數字),服務器以此確認登陸者是用戶本人。node
兩步驗證從用戶體驗的角度來講確定是不友好的,由於用戶登陸或者操做一個開啓兩步驗證的網站時,用戶須要額外輸入一串隨機密碼以確認用戶是本人操做。對於大多數人來講可能以爲這操做就是多餘的,麻煩的。這麼麻煩不如關掉。git
我建議對於比較重要的帳號,若是該應用提供了兩步驗證,最好開啓。安全第一。github
我舉一下我身邊的一個栗子?
大概是2016年,我女友的Apple ID被盜。盜號者解綁了她的郵箱,改用盜號者的郵箱,致使女友iPhone被鎖。盜號者還發郵件勒索500元解鎖,我還加了盜號者qq和他砍價,砍到了200元。最後固然是找蘋果客服解鎖,提供了各類照片、單據和電話確認,歷時2天才解鎖。整體沒什麼損失,就是給本身生活帶來一些不便。看看知乎上被盜號而且盜刷信用卡支付寶的,那才叫慘烈。
若是被盜者開啓了兩步驗證,即便別人有你的Apple ID的帳號密碼,也登陸不了你的帳號。算法
另外,可能不少用戶喜歡在多個網站上使用相同的密碼,這樣是很危險的。若是用戶一個網站上的帳號被盜了,其它平臺的帳號可能也要遭殃。畢竟「某某平臺的帳號系統被盜」這種事也是時有發生的。這種狀況開啓兩步驗證也是能保護其它平臺的帳號不被不法分子利用。npm
兩步驗證中使用的密碼是一次性密碼(One-Time Password 簡稱OTP),也稱爲動態口令。是使用密碼技術實現的在客戶端和服務器之間經過共享密鑰的一種強認證技術,是加強目前靜態口令認證的一種很是方便技術手段,是一種重要的兩步驗證認證技術。Wikipedia解釋瀏覽器
HOTP 是基於 HMAC 算法生成的一次性密碼,也稱事件同步的動態密碼,是 ITEF RFC 4226 公開的算法規範, 僞代碼以下:
<center>HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
</center>
客戶端和服務器事先協商好一個密鑰K,用於一次性密碼的生成。客戶端和服務器各有一個事件計數器C,而且事先將計數值同步。Truncate是將HMAC-SHA-1產生的20字節的字符串轉換爲若干位十進制數字的算法。安全
TOTP 是 HOTP 的改良版,使用時間替換掉 HOTP 的事件計數器 C,也稱時間同步的動態密碼。詳細規範見 RFC 6238,僞代碼:
<center>TOTP = Truncate(HMAC-SHA-1(K,T))
</center>
T = (Current Unix time - T0) / X
T0 是初試時間,默認爲 0
X 是時間步長,默認30秒
官方文檔中舉了個栗子,假設當前unix時間=59,T0=0,X=30,則T=1
假設當前unix時間=60,T0=0,X=30,則T=2
也就是對T的值向下取整,拋棄小數的意思
瞭解完了規範後,擼代碼就簡單了。
上面的算法除了HMAC-SHA-1以外就是Truncat了,貼一段Truncat的JS代碼:
// 將20字節的hmac結果轉爲6位數字,不夠6位前面補0 truncat(hmac_result) { const offset = hmac_result[19].charCodeAt() & 0xf; const bin_code = (hmac_result[offset].charCodeAt() & 0x7f) << 24 | (hmac_result[offset + 1].charCodeAt() & 0xff) << 16 | (hmac_result[offset + 2].charCodeAt() & 0xff) << 8 | (hmac_result[offset + 3].charCodeAt() & 0xff); let otp = (bin_code % 10 ** this.digit).toString(); while (otp.length < this.digit) { otp = '0' + otp; } return otp; }
代碼已上傳npm,支持node.js和瀏覽器執行
完整代碼請移步個人Github https://github.com/wuyanxin/t...
npm install totp.js
const TOTP = require('totp.js'); // generate a base32 secret key const key = TOTP.randomKey(); // 'GAXGGYT2OU2DEOJR' const totp = new TOTP(key); const code = totp.genOTP(); // '552179' totp.verify(code) // true // generate Google Authenticator supported URL totp.gaURL('handsome@totp.js', 'Totp.js') // 'otpauth://totp/handsome@totp.js?issuer=Totp.js&secret=GAXGGYT2OU2DEOJR' // OR const totp2 = new TOTP(TOTP.base32.encode('your key')); totp2.genOTP()
歡迎轉載,轉載請附上 原文連接