Authentication

在 HOTP 實現中公開提供下一個計數器是否被認為是不安全的?

  • June 13, 2013

我正在開展一個項目,該項目需要使用在微控制器上執行的伺服器安全地驗證一個或多個智能手機客戶端,因此它的資源非常有限。我發現了很多輕量級的 HMAC 雜湊庫。因此,在我看來,HOTP 身份驗證機制在微控制器的有限資源上是可行的。

然而,我擔心的是多個客戶端的身份驗證。我知道理想情況下(或者我被告知)在 HOTP 實現中,每個客戶端都將擁有自己與伺服器共享的密鑰。但是,我沒有資源在微控制器上擁有共享密鑰數據庫。

我想知道是否可以讓所有客戶端和伺服器共享相同的密鑰並讓伺服器告訴任何請求它的客戶端下一個預期的計數器是什麼。這將是一個未經身份驗證的請求,只會提供預期的計數器。然後,客戶端可以發出一個經過身份驗證的命令,其中包含一個 HOTP 程式碼(使用提供的計數器),該命令將實際執行所需的操作。

根據定義 HOTP 的 RFC,即使伺服器將相同的計數器提供給 2 個客戶端,每個計數器也只會被接受一次,在這種情況下,第一個獲勝,第二個需要獲得下一個計數器。

我知道這不是很理想,但這是我能想到的最好的實現。安全性是關於平衡弱點與可用性或在我的情況下是伺服器限制。這是用於門解鎖機制的價值。我認為我的實現至少與典型的物理密鑰一樣好。

這裡的安全影響和權衡是什麼?鑑於伺服器無法維護多個密鑰的限制,是否有更好的實現(HOTP 與否)?

RFC 4226,第 7.5 節定義了兩種共享密鑰生成方案:確定性和隨機性。我建議您使用確定性方案,它只需要伺服器儲存一個“主密鑰”:

確定性生成

一種可能的策略是從主機密中導出共享機密。主密鑰將僅儲存在伺服器上。必須使用防篡改設備來儲存主密鑰並從主密鑰和一些公共資訊中獲取共享秘密。主要好處是避免在任何時候暴露共享秘密,並避免對儲存的特定要求,因為共享秘密可以在配置和驗證時按需生成。”

**附錄:**為了避免為每個客戶端儲存單獨的計數器值,您仍然可以按照您的建議為所有客戶端使用共享計數器,至少只要伺服器的預期目的是不可能用於多個合法客戶端嘗試同時進行身份驗證。

然而,簡單地向客戶端發送一個計數器值並讓客戶端使用相應的一次性密碼進行回复可能允許偽裝成伺服器的攻擊者向客戶端發送人為的高計數器值並儲存響應以供以後使用。(如果客戶端強制執行計數器值的單調性,這也可能導致客戶端暫時無法進行身份驗證,直到伺服器的計數器趕上攻擊者發送的虛假計數器值。)

避免這種攻擊消除請求計數器的額外往返的一種方法是使用時間戳作為計數器,如下所示:

  • 當使用者想要認證時,伺服器向伺服器發送目前時間戳 $ T $ , 它的客戶 ID $ i $ 和一次性密碼 $ P = HOTP(K_i,T) $ , 在哪裡 $ K_i $ 是客戶端的 HOTP 密鑰。

  • 收到身份驗證請求時 $ (T,i,P) $ ,伺服器檢查:

    • $ i $ 是有效且未撤銷的客戶 ID;
    • $ T $ 是一個有效的時間戳,並且在過去或未來都不會太遠;
    • $ T $ 大於時間戳 $ T’ $ 用於之前的成功認證;和
    • $ P = HOTP(K_i,T) $ , 在哪裡 $ K_i $ 是從客戶端 ID 派生的客戶端密鑰 $ i $ 和萬能鑰匙 $ MK $ .如果所有這些檢查都通過,則允許客戶端訪問。

因此,伺服器只需要儲存主密鑰 $ MK $ , 最後一次成功的認證時間戳 $ T’ $ ,以及可能的已撤銷客戶端 ID 列表。(這種撤銷受感染客戶端訪問權限的能力是在客戶端之間不共享密鑰的主要優勢之一。)

有效時間視窗允許客戶端和伺服器之間存在一定程度的時鐘偏差,並且應該設置為反映該偏差和安全要求之間的平衡。

攔截此協議中的身份驗證請求的攻擊者實際上並不能做太多事情:如果他們將請求傳遞給伺服器,他們剛剛擷取的密碼將變得無用(並且如果客戶端和伺服器使用他們的共享密鑰加密任何進一步的通信 $ K_i $ ,攻擊者甚至無法竊聽它);如果他們不這樣做,客戶端就會知道出了什麼問題,並且無論如何密碼仍然會在有限的時間視窗過去後過期(如果客戶端嘗試重新驗證並成功,可能會更快)。

(顯然,該協議還需要防止暴力攻擊,方法是按照 HOTP 規範中的建議實施請求速率限制,和/或使密碼足夠長。事實上,如果密碼不需要人工輸入,一個也可以——實際上,最好——使用完整的非截斷 HMAC 輸出作為一次性密碼。)

引用自:https://crypto.stackexchange.com/questions/3860