Xor

對已知密鑰長度的zlib壓縮的二進制數據進行攻擊異或加密(非常短的密鑰)

  • November 13, 2013

我正在嘗試破壞數據包格式。數據包格式只是將幾個文件打包成一個大文件。文件內容很簡單。但是包含偏移量、文件大小和文件名的索引數據是加密的。索引數據大約 1 KB 並由 zlib(沒有 zlib 或 gzip 包裝器的 DEFLATE 算法)壓縮,然後進行 XOR 加密。換句話說,將密鑰與自身連接多次以獲得與 zlib 壓縮數據相同長度的密鑰流,然後將 zlib 壓縮數據與該密鑰流進行異或(如 Vigenère 密碼)。我知道密鑰長度是 8 個字節。是否可以解密數據?

如果您知道純文字,即一個完整已知的輸入文件,那麼這很容易破解。因此,如果您不知道壓縮的輸入文件中的內容,我將探討可能導致中斷的方法。

我建議您從仔細分析DEFLATE 流格式開始(另請參閱這些方便的註釋)。這可能會幫助您得出一些 DEFLATE 流的前幾位必須滿足的一致關係。

乍一看,在我看來,DEFLATE 流的開頭具有以下結構:

  • 正如 Stephen Tousot 所解釋的,在正常操作中,DEFLATE 流的前 3 位可能是 110。(您可能需要使用您正在使用的壓縮程序仔細檢查這一點。)
  • 接下來的三個欄位是 HLIT(5 位)、HDIST(5 位)和 HCLEN(4 位)。我建議您獲取一組典型的應用程序範例輸入,使用您正在使用的壓縮實現對其進行壓縮,然後查看生成的 DEFLATE 流中 HLIT、HDIST 和 HCLEN 的典型值範圍。我懷疑您可能會發現並非所有值的可能性都相同。
  • 在上述 17 位之後是 3*(HCLEN+4) 位的塊,它被解釋為 3 位值的序列。如果我正確理解了 DEFLATE 算法(我可能不會),如果您使用 DEFLATE 規範中的固定排列適當地排列這些並忽略所有 000 值,那麼剩餘的 3 位值應該按排序順序排列。這為這些位的可能值提供了額外的約束。
  • 然後還有一些我現在忽略的東西。

例如,如果 HCLEN=15,則上面的前三項占 DEFLATE 流的前 74 位。而且,如果我理解正確,上述結構對位強加了一些一致性關係:並非所有可能的 74 位序列都是可能的(並且並非所有可能的序列都同樣可能)。

現在,我認為您可以使用以下過程來嘗試恢復密鑰 $ K $ .

  • 對於 64 位密鑰的每個候選值 $ K $ , 將其與密文的前 64 位進行異或運算得到 $ Y = C\oplus K $ ,對 DEFLATE 流的 64 位的猜測。檢查是否 $ Y $ 符合上述約束條件。如果不一致,繼續尋找下一個候選人 $ K $ .
  • 如果一致,則使用以下方法對整個密文進行試解密 $ K $ (即,異或重複版本的 $ K $ 對密文,然後解壓縮)。查看生成的明文是否看起來像是一個合理的輸入。如果是,你可能已經找到了鑰匙 $ K $ . 如果沒有,請繼續尋找下一位候選人。

如前所述,這種方法需要 $ 2^{64} $ 循環的迭代。但是,如果您對如何檢查密鑰有點聰明,我懷疑您可能可以加快速度 $ K $ . 我認為您可以使用類似樹的迭代加深方法,而不是逐個迭代所有可能的 64 位值。這個想法是,粗略地說,如果你拒絕(比如說)17 位前綴 $ K $ 如果不可能,則無需嘗試以該前綴開頭的任何鍵。因此,優化的算法可能首先檢查所有候選值的前 17 位 $ K $ (比如說)要查看哪些看起來一致,然後對於每個倖存的 17 位前綴,您希望找到所有可行的方法將其擴展 3 位,依此類推,在每一步重複。

我不知道這個更複雜的算法的執行時間是多少,但是如果你仔細研究 DEFLATE 格式並且能夠對 DEFLATE 流的前 64 位進行足夠的一致性檢查,你也許可以做到這一點攻擊執行效率足夠實用。

我意識到我還沒有為你解決所有的細節——我給你留下了一些東西讓你自己做。但希望這能讓你開始,並為你提供一些可能導致實際攻擊的方向的想法。

詳細說明評論將您引向…

這種加密方案容易受到直接的已知明文攻擊

密文的每個字節都將按照以下格式加密:

$$ C_i = P_i \oplus K_{i\ \bmod{\ len(K)}} $$ 在哪裡 $ i $ 是密文和明文中的字節索引。這個表達式很容易解決關鍵:

$$ K_{i\ \bmod{\ len(K)}} = C_i \oplus P_i $$ 換句話說:您顯然知道密文,因此如果您還可以在給定字節位置學習明文,那麼您只需將明文字節與其相應的密文字節進行異或運算即可學習相應的密鑰字節。(由於密鑰是重複的,因此您需要確定從 0 到 7 之間的哪個密鑰字節索引複製了該密鑰字節。)一旦您了解了密鑰的所有 8 個字節,只需以與加密相同的方式連接它並使用生成的流以解密密文。

但是你怎麼能找到明文呢?最簡單的起點是查看壓縮數據格式的規範。確定使用的確切格式,然後查找它使用的標頭值和資料結構類型。某些格式具有某些始終具有某些固定值的字節位置,或者某些結構具有易於猜測的內容。不要只尋找完整的字節,如果你能確定一個字節的一些位也是有用的。

如果這還不夠,您可能需要考慮嘗試生成已知的明文,然後對其進行加密。例如,獲取一些文本並使用遵循完全相同壓縮規範的不同程序對其進行壓縮,該程序將在加密之前生成明文(或非常接近明文的內容)(也稱為選擇明文攻擊)。

如果您只能使用這些方法破壞密鑰的幾個字節,那麼您可能能夠以蠻力完成。(如果你有耐心的話,在一台合理的現代家用電腦上,3 到 4 個字節肯定是暴力破解的。)修復你確定的關鍵字節並迭代未知的關鍵字節。使用每個潛在的密鑰對擷取的數據包數據進行解密,並查看密鑰是否生成有效的解密壓縮數據(可能呼叫解壓縮函式,查看它返回成功還是錯誤)。(如果太多的測試密鑰產生有效的壓縮明文,請使用相同的密鑰和針對所有這些密鑰的密鑰加密幾個數據包,您必須測試的數據越多,您就越有可能消除錯誤的密鑰。)

從生成有效壓縮數據的密鑰中,測試解壓縮的數據,看看它是否符合您的預期,因為您說您知道加密數據是什麼。檢查它是否看起來像有效的文件名等,適當的 ASCII 或其他。如果你有相當少的鍵可以做到這一點,那麼在這裡觀察它會很好用。

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