Stream-Cipher

流式傳輸 API 到經過身份驗證的加密

  • October 5, 2016

關於 NaCl,我問 DJB ,他是否打算將流 API 添加到經過身份驗證的密碼中。回想起來,他的回答很明顯,在驗證身份驗證者之前,永遠不應該發布解密的明文。

然而,這讓我開始思考。流式傳輸很重要——例如,在處理非常大的數據集時。模仿流媒體介面是否可能,甚至是可取的?

一種簡單的方法是每隔一定數量的塊對數據進行分塊。收到足夠的塊後,將 IV 和完整的密文輸出到加密流中。當你收到下一組塊來完成一個塊時,生成一個新的 IV 並重複。要解密,請獲取加密流的第一個塊,並將其視為第一個 IV。讀取一個完整的塊,然後解密。將結果作為第一塊純文字輸出。重複。

這將通過經過身份驗證的密碼執行所有數據,並在發布明文之前驗證身份驗證者,但在發布某些明文之前不會驗證整個密文。這是有問題的,還是通常認為是安全的?根據您的特定問題,在某些情況下是否安全?或者它總是會引入嚴重的缺陷?

我意識到這很好地進入了滾動你自己的加密領域,並且不打算自己實施。也就是說,對這種方法的判斷是什麼?該問題是否有替代解決方案?是否有一種通用方法可以用來安全地加密具有身份驗證模式的超大型數據集,或者是否有任何解決方案仍然高度依賴於要解決的確切問題?

更新:Hoang、Reyhanitabar、Rogaway 和 Vizár 發表了一篇論文,定義了解決此問題的“STREAM”協議。

正如問題中所指出的,經過身份驗證的加密的保守 API 應該只在解密端發布經過身份驗證的明文。其他任何東西都太容易受到攻擊(填充、時間、拒絕服務、未經允許)。

在流式 API 中,這會強制將數據聚合成塊,每個塊都經過身份驗證。最簡單的方法是固定大小的密文塊(與明文特性相關的塊,例如在文本的行尾,太容易受到資訊洩漏的影響;接收方的按需阻塞需要對通信鏈路進行回饋,這可能會洩漏資訊,而且過於復雜)。

阻塞的一個明顯缺點是它增加了成本。然而,即使每個塊有 128 位的成本(這對於 IV 和身份驗證器來說已經足夠了),8kiB 的阻塞導致的成本不到 0.1%,這在許多案例中是可以接受的。這基本上就是 OP 所提議的。

這種阻塞策略的另一個非常現實的問題是,我們必須抵制對手對已驗證塊的壓制、複製和重新排序,以相應地改變明文。問題中提出的方案沒有,並且容易受到這些攻擊

為了糾正這種情況,一種方法是在經過身份驗證的數據中包含一個塊序列號,在數據開始時從 0 開始,並在每個塊處加一。這甚至不一定會增加大小成本,因為這個塊號既不需要加密,也不需要顯式傳輸。使用GCM,我們可以將這個塊號隱式包含在經過身份驗證的數據中,但不會傳輸。使用 Encrypt-then-MAC 認證加密,我們可以在加密之後和 MAC-ing 之前插入塊號。使用 MAC-then-encrypt 認證加密,我們可以在 MAC-ed 數據中輸入這個塊號,並在加密前將其刪除。

另一種糾正方法是為每個塊使用不同的密鑰,使用快速KDF生成它們。

通過這樣的調整,除了明顯的固有(但實際上可以接受的)危險之外,我沒有看到使用帶有阻塞的認證加密、打包在流式 API 中以進行認證加密的任何系統性缺陷,特別是

  • 攻擊者可以中斷經過身份驗證的數據流,並從接收者對此的反應中推斷出一些東西,特別是如果存在“從開始重做”以外的重試機制時。
  • 接收者可能會根據塊中的內容執行對手可檢測到的動作;這足以洩漏在非阻塞認證加密中不會洩漏的資訊(例如,假設明文已知包含 98 或 99 個!字元,間距遠大於塊大小,每個都會!導致接收器上的功耗突發敵方每秒讀取一次功率計讀數,從而可靠地辨別是否發生了爆發。然後在使用阻塞時,她可以使用它來確定是 98 還是 99!字元,通過將資訊流限制在兩個儀表讀數之間的一個塊內;假設兩個連續功率讀數之間的差異存在 5% 的不確定性,如果沒有阻塞,這可能是不可能的)。

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