業餘草雙因素認證(2FA)教程

業餘草發表於2017-11-02
所謂認證(authentication)就是確認使用者的身份,是網站登入必不可少的步驟。
密碼是最常見的認證方法,但是不安全,容易洩露和冒充。

越來越多的地方,要求啟用雙因素認證(Two-factor authentication,簡稱 2FA)。本文介紹它的概念和實現方法。

我的部落格:CODE大全www.codedq.net業餘草www.xttblog.com愛分享www.ndislwf.comifxvn.com

雙因素認證的概念

一般來說,三種不同型別的證據,可以證明一個人的身份。
  • 祕密資訊:只有該使用者知道、其他人不知道的某種資訊,比如密碼。

  • 個人物品:該使用者的私人物品,比如身份證、鑰匙。

  • 生理特徵:該使用者的遺傳特徵,比如指紋、相貌、虹膜等等。
這些證據就稱為三種"因素"(factor)。因素越多,證明力就越強,身份就越可靠。
雙因素認證就是指,通過認證同時需要兩個因素的證據。
銀行卡就是最常見的雙因素認證。使用者必須同時提供銀行卡和密碼,才能取到現金。

雙因素認證方案

常用的雙因素組合是密碼 + 某種個人物品,比如網上銀行的 U 盾。使用者插上 U 盾,再輸入密碼,才能登入網上銀行。

但是,使用者不可能隨時攜帶 U 盾,手機才是最好的替代品。密碼 + 手機就成了最佳的雙因素認證方案。

國內的很多網站要求,使用者輸入密碼時,還要提供短訊息傳送的驗證碼,以證明使用者確實擁有該手機。

但是,短訊息是不安全的,容易被攔截和偽造,SIM 卡也可以克隆。已經有案例,先偽造身份證,再申請一模一樣的手機號碼,把錢轉走。
因此,安全的雙因素認證不是密碼 + 短訊息,而是下面要介紹的 TOTP。

TOTP 的概念

TOTP 的全稱是"基於時間的一次性密碼"(Time-based One-time Password)。它是公認的可靠解決方案,已經寫入國際標準 RFC6238。


它的步驟如下。
第一步,使用者開啟雙因素認證後,伺服器生成一個金鑰。
第二步:伺服器提示使用者掃描二維碼(或者使用其他方式),把金鑰儲存到使用者的手機。也就是說,伺服器和使用者的手機,現在都有了同一把金鑰。


注意,金鑰必須跟手機繫結。一旦使用者更換手機,就必須生成全新的金鑰。
第三步,使用者登入時,手機客戶端使用這個金鑰和當前時間戳,生成一個雜湊,有效期預設為30秒。使用者在有效期內,把這個雜湊提交給伺服器。


第四步,伺服器也使用金鑰和當前時間戳,生成一個雜湊,跟使用者提交的雜湊比對。只要兩者不一致,就拒絕登入。

我的部落格:CODE大全www.codedq.net業餘草www.xttblog.com愛分享www.ndislwf.comifxvn.com

TOTP 的演算法

仔細看上面的步驟,你可能會有一個問題:手機客戶端和伺服器,如何保證30秒期間都得到同一個雜湊呢?
答案就是下面的公式。
TC = floor((unixtime(now) − unixtime(T0)) / TS)
上面的公式中,TC 表示一個時間計數器,unixtime(now)是當前 Unix 時間戳,unixtime(T0)是約定的起始時間點的時間戳,預設是0,也就是1970年1月1日。TS 則是雜湊有效期的時間長度,預設是30秒。因此,上面的公式就變成下面的形式。
TC = floor(unixtime(now) / 30)
所以,只要在 30 秒以內,TC 的值都是一樣的。前提是伺服器和手機的時間必須同步。
接下來,就可以算出雜湊了。
TOTP = HASH(SecretKey, TC)
上面程式碼中,HASH就是約定的雜湊函式,預設是 SHA-1。
TOTP 有硬體生成器和軟體生成器之分,都是採用上面的演算法。


(說明:TOTP 硬體生成器)


(說明:Google Authenticator 是一個生成 TOTP 的手機 App)

TOTP 的實現

TOTP 很容易寫,各個語言都有實現。下面我用 JavaScript 實現2fa來演示一下真實程式碼。
首先,安裝這個模組。
$ npm install --save 2fa
然後,生成一個32位字元的金鑰。
var tfa = require('2fa');

tfa.generateKey(32, function(err, key) {
  console.log(key);
});
// b5jjo0cz87d66mhwa9azplhxiao18zlx
現在就可以生成雜湊了。
var tc = Math.floor(Date.now() / 1000 / 30);
var totp = tfa.generateCode(key, tc);
console.log(totp); // 683464

總結

雙因素認證的優點在於,比單純的密碼登入安全得多。就算密碼洩露,只要手機還在,賬戶就是安全的。各種密碼破解方法,都對雙因素認證無效。
缺點在於,登入多了一步,費時且麻煩,使用者會感到不耐煩。而且,它也不意味著賬戶的絕對安全,入侵者依然可以通過盜取 cookie 或 token,劫持整個對話(session)。
雙因素認證還有一個最大的問題,那就是帳戶的恢復。


一旦忘記密碼或者遺失手機,想要恢復登入,勢必就要繞過雙因素認證,這就形成了一個安全漏洞。除非準備兩套雙因素認證,一套用來登入,另一套用來恢復賬戶。

我的部落格:CODE大全www.codedq.net業餘草www.xttblog.com愛分享www.ndislwf.comifxvn.com

參考連結

原文連結:http://www.ruanyifeng.com/blog/2017/11/2fa-tutorial.html

相關文章