[RFC6238] TOTP: 基於時間的一次性密碼生成算法

在閒暇時間做了一個TOTP相關的開源項目,在項目初步完成之餘,我嘗試對[RFC6238]文檔進行了翻譯,供大家參考與查閱,若有不妥之處,還望各位前輩海涵斧正。

 

生活中我們會經常使用到TOTP的算法應用,如銀行的動態口令器、網絡遊戲中的將軍令、登錄場景下的手機二次驗證等等。

 

下圖便是一個常見的OTP動態密碼生成器:

圖片

 

爲了提高遊戲賬號的安全性我們在輸入賬號密碼後,對於綁定了將軍令的用戶還需要輸入將軍令(OTP動態口令生成器)上面的一次性動態密碼,驗證通過後方纔登陸成功。

圖片

 

文章提要


 

這篇文檔主要講述了關於一次性密碼(OTP)的一個擴展算法,此算法是在,RFC4226文檔中定義的'基於HMAC的一次性密碼算法'基礎之上,支持了基於時間移動因子的擴展算法。

HOTP算法是一個以事件計數器作爲移動因子,基於事件的一次性密碼算法。

本文所講述的算法則是將時間值作爲移動因子。

這個基於時間的一次性密碼生成算法提供了有效時間更短的一次性密碼,增強了OTP算法的安全性。

此算法可以廣泛的應用於互聯網應用之中,包括遠程虛擬專用網絡(VPN)的訪問控制,Wi-Fi網絡登錄以及面向交易的網絡應用等等。

作者相信通過商用和開源的算法實現,一個通用的共享算法將會促進互聯網上更多的人接觸並使用到雙因素身份認證算法。

概要


本文主要描述了一次性密碼(OTP)的一個擴展算法,此算法是支持將時間作爲移動因子的一個基於HMAC的一次性加密算法。

背景

在4226文檔中描述中,HOTP算法是基於HMAC-SHA-1算法並用一個自增的計數值器來作爲HMAC計算中的消息。

基本上,HMAC-SHA-1的計算輸出結果都會截取爲一串對用戶友好的值。

HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

Truncate函數表示它能夠將HMAC-SHA-1的計算結果轉換成HOTP的結果值。K表示共享密鑰,C表示計數值,詳情請看[RFC4226]。

TOTP算法是上述算法基於時間的變體,使用通過時間戳和時間步長推導出來的數值T來代替原有HOTP算法中的計數器C。

TOTP算法的實現可以採用HMAC-SHA-256或HMAC-SHA-512函數,用此來代替原有HOTP計算中採用的HMAC-SHA-1方案。

算法要求

這一部分概括性的總結了,在設計TOTP算法時需要考慮的方面。

  1. 證明者和驗證者都必須知道或者能夠根據Unix時間推導得出OTP。證明者所提供的時間精度將會影響到需要多久進行一次時鐘同步。

  2. 證明者和驗證者必須分享相同的密鑰或者密鑰生成轉換的方法。

  3. 算法必須使用HOTP算法來進行關鍵塊構建。

  4. 證明者和驗證者必須使用相同的時間步長X。

  5. 對於每一個證明者必須要分配唯一的密鑰Key。

  6. 密鑰Key應該是隨機生成的或導出密鑰推導算法。

  7. 密鑰key可以存放在防篡改的設備之中並防止未經授權的非法訪問。

TOTP算法

TOTP算法是用時間因子來表示計數器的一種計算一次性密碼的HOTP算法的變體。

釋義

 

  • X表示以秒爲單位的時間步長(默認爲30秒),它是一個系統參數。

 

  • T0是開始計步的起始Unix時間(默認是0,即)也是一個系統參數。

描述

一般而言,我們將TOTP定義爲TOTP = HOTP(K, T),其中T是一個整數,代表了在初始時間T0和當前Unix時間之間的時間步長。

更具體的說,T = (Current Unix time - T0) / X,默認在計算時向下取整。

比如,T0=0,X=30時,當前Unix時間爲59秒那麼T=1,當前Unix時間爲60秒時,那麼T=2。

算法的實現必須支持,當時間T超過2038年後,時間數值大於32位整數這種情況。系統參數X和T0是預先就確定好的了,作爲準備步驟的一部分,已經在客戶端和服務端進行了同步。相關的同步流程已超出了本文檔的表述範圍,詳情請見[RFC6030]。

基於安全的考量

常規的

算法的安全性和可靠程度依賴於用於構建HOTP塊的屬性參數。它是在構造HMAC時使用的SHA-1作爲哈希函數。

通過[RFC4226]中詳盡的安全性分析結論得知,在所有真實場景下,針對不同的輸入,所得到的輸出結果截斷,都是相互獨立且沒有必然聯繫的字符串。

分析表明,針對HOTP最有可能的破解方式就是暴力破解。

如算法實現中要求的那樣,密鑰key應當選擇隨機值或者通過設置了合理隨機種子安全的強僞隨機數生成器生成隨機數。

密鑰的長度應當與HMAC的輸出長度一致,已達到複用。

對於僞隨機數以及隨機數生成器相關的事項,建議遵從[RFC4086]的規則定義。用於生成密鑰的僞隨機數要求能夠通過在[CN]中指定的隨機性測驗或者其他公認的測試。

所有通信應該建立在安全通道之上,例如安全套接字層/傳輸層安全或IPsec連接。

我們也同樣建議將密鑰安全地存放在認證系統之中,更加具體的講,使用防篡改的硬件來加密客戶端的密鑰。僅當,真的有必要時纔將其暴露出來,比如在認證一次性密鑰是否正確是,需要對密鑰進行解密,當此操作完成之後便立即重新加密,以此來最大限度地縮短密鑰明文變量暴露在內存中時間。

密鑰必須存放在安全可靠的地方,以儘可能的避免對認證服務器系統和存放密鑰的數據庫的直接攻擊。
特別是,獲取密鑰信息這一操作應當被限制在驗證系統所必須的程序或相關執行過程之中。

驗證和時間步長

在相同的時間步數內生成的一次性密碼結果是一樣的。當驗證服務器接收到一個一次性密碼時,它並不知道客戶端具體是在何時生成的這個一次性密碼。驗證服務器或許會使用接收到客戶端密碼的這個時間來生成密碼並與客戶端密碼進行比較。

但由於網絡延遲,客戶端生成出一次性密碼的時間和服務端接收到的時間差距(用T進行計量,它是從T0開始的時間時間步數)可能會很大。驗證服務器接收到的時間和實際生成一次性密碼的時間有可能不會落在同一個時間計步窗口下,由此可能會產生兩個不一致的一次性密碼。

當客戶端生成一次性密碼的時間在時間計步窗口靠後的位置,那麼服務端收到密碼的時間就很有可能會落到下一個計步窗口之中。驗證服務器通常要爲因傳輸延遲而不能匹配有效的一次性密碼的情形設置相應的延時窗口來進行驗證。

這樣的話,認證系統就不應當用接收到一次性密碼的時間來生成比較密碼了,還需要將在傳輸時延內的那些密碼也要包含進去進行驗證。越大的可接受時延窗口會暴露出更大的攻擊窗口。所以我們建議最多使用一個時間步長來應對網絡時延問題。

時間步長影響着系統的安全性和可用性。一個更大的時間步長意味着認證系統要設置更大的一次性密碼的可接受窗口。

使用更大的時間步長會關聯到以下幾個方面:

首先,更大的時間步長會暴露出更大的可攻擊窗口。當一次性密碼生成完成並在失效之前暴露給第三方,那麼第三方就能夠在這個時間窗口內繼續使用這個一次性密碼。

我們建議默認的時間步長爲30秒。將其設置爲30秒是綜合考慮了安全性和可用性的結果。

第二,下一個不同的一次性密碼只能在下一個時間窗口下才能生成。一個用戶必須等到時鐘到了下一個時間窗口內才能進行新的提交。這個等待時間不一定等於時間步長,它依賴於最後一次生成一次性密碼的時間。

比如,如果最後一次生成一次性密碼的時間是在時間窗口的一半的位置,那麼等待生成下一個一次性密碼的時間就會是步長的一半。一般而言,越大的時間步長意味着用戶需在上一個成功的一次性密碼驗證之後,需要等待更長的時間才能夠生成下一個合法的一次性密碼來進行新的驗證。

一個超大的窗口,比如十分鐘,很可能不適合典型的互聯網用戶的登錄需求。用戶無法在十分鐘之內獲取到下一個一次性密碼,所以就讓他等十分鐘再來登陸嗎?

注意,認證者可以在相同的時間窗口內多次發送相同的一次性密碼到服務器上來進行認證。所以在同一個時間窗口下服務器在第一個一次性密碼驗證成功之後就不能在接受驗證第二個一次性密碼了,這也確保了一個時間內只使用一個一次性密碼(否則一個30秒的時間窗口,暴力輪接口肯定能把6位密碼給攻破)。

同步校準機制

由於可能存在客戶端時鐘和認證服務器的時鐘不同步的問題,我們建議驗證者在拒絕掉客戶端'錯誤的'認證之前,通過設置步長的方式對不同步的時間進行校準。

這個限制可以是,從收到OTP值時的計算時間開始,向前和向後設置以步長爲單位的時間,如果時間步長設置爲30秒,驗證者要向後設置兩個時間步長,如果這樣的話最大的漂移時間就會在89秒左右(允許客戶端與服務器有89秒的誤差),即用於計算的那個時間步長內剩餘的29秒和向後的兩個時間步長的60秒。

這意味着驗證器會用當前時間窗口執行驗證,也會用由此向後的兩個時間窗口再進行驗證(一共是三個時間窗口的驗證)。認證成功之後,認證服務器可以記錄所偵測到的時鐘漂移。在此步驟之後,當收到一個新的一次性密碼時,認證者可以通過當前時間和之前記錄的時鐘漂移步長得出的一個校準後的時間來驗證客戶端的一次性密碼。

同樣,需要注意的是,客戶端未向服務器發送一次性密碼的時間越長,由此積累的時鐘漂移就有可能會越來越大。在這樣的場景下,如果漂移量大於程序所允許的閾值的話,那麼自動校準功能可能就會失效。這時就應該使用其他的認證方式進行安全身份驗證,並強制校準客戶端與服務端的時鐘,使二者保持同步。

 
作者:翎野君
博客:https://www.cnblogs.com/lingyejun/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章