Hash

將兩個 sha512 雜湊合併為一個雜湊

  • August 21, 2015

假設我有兩個數據片段: $ Frag_1 $ 和 $ Frag_2 $ .

我可以用通常的方式建構 sha512 雜湊 $ SHA512(Frag_1) $ 和 $ SHA512(Frag_2) $ 然後散列彼此附加的兩個片段:

$$ SHA512(Frag_1 | Frag_2) $$ 我的問題是,有沒有辦法將這兩個片段的散列組合起來,以便可以計算它們附加版本的散列?

更準確:有沒有操作(這裡用紅色問號表示“ $ \color{red} ? $ “), 以便

$$ SHA512(Frag_1)\ \color{red} ?\ SHA512(Frag_2) == SHA512(Frag_1 | Frag_2) $$ 是否可以創建長度為 sha512 塊大小的倍數的數據片段?

大多數標準使用的迭代散列函式(包括 SHA-512)的建構方式使得這些類型的操作是不可能的(不破壞散列函式)。

它們通常以這種方式工作:

  • 消息被分成相同大小的塊(通常在末尾有一些填充以填充最後一個塊): $ pad(M) = M_0 || M_1 || M_2 … || M_n $ .
  • 有一些內部“狀態” $ S $ , 初始化為固定值 $ S_0 $ 在開始時
  • 對於每個塊,一些內部函式 $ C $ (通常稱為“壓縮函式”)應用於舊狀態和消息塊以產生新狀態: $ S_{i+1} = C(S_i, M_i) $
  • 最後,要麼直接輸出最後一個狀態,要麼(在更現代的散列函式中)另一個函式 $ O $ 應用於該狀態以產生最終的雜湊輸出: $ h(M) = O(S_{n+1}) $

因此,例如,對於 4 塊消息(填充後),我們有

$$ h(M) = O(C(C(C(C(S_0, M_0), M_1), M_2), M_3)). $$ 壓縮函式通常以即使其中一個輸入的微小變化也會產生完全不同的輸出的方式建構,因此沒有簡單的方法可以從輸出返回到輸入。(這通常形式化為*“ $ C $ 是一種單向函式”*。)(有時狀態的某些部分會被特殊處理,並且可以很容易地追溯,例如在 Skein 中,它們包含一個計數器。SHA-256 不是這種情況,在 Skein 中也是如此不會傷害任何東西,因為輸出不包括它們。)

即使假設沒有填充,O 是身份並且我們的片段都只有一個塊的大小,我們得到 $ h(F_1) = C(S_0, F_1) $ , $ h(F_2) = C(S_0, F_2) $ 和 $ h(F_1||F_2)) = C(C(S_0, F_1), F_2) $ . 雖然我們也可以將後者寫為 $ h(F_1||F_2)) = C(h(F1), F_2) $ ,壓縮函式的單向屬性不允許我們從 $ C(S_0, F_2) $ .

但如果你有 $ F_2 $ 實際上給出的,不僅僅是它的雜湊,你可以使用它來創建 $ F_1||F_2 $ ,即使不知道 $ F_1 $ . 這被稱為迭代雜湊的長度擴展屬性,其輸出轉換為身份。

實際上,填充的存在使情況變得複雜,但是您仍然可以為類似的東西創建雜湊 $ F_1 || P || F_2 $ , 你知道的 $ h(F_1) $ (但不是 $ F_1 $ 本身), $ P $ 是一些填充取決於長度 $ F_1 $ (實際上並不需要您知道),並且 $ F_2 $ 是您選擇的字元串)。

使用非平凡的輸出轉換會阻止這一點——可能的方法是應用一些簡單的截斷(如 SHA-384,它本質上是具有不同初始狀態和結果截斷的 SHA-512),或其他一些壓縮函式 -像轉型。或者簡單地將整個散列函式再次應用於結果(例如,在比特幣協議中用作 SHA-256d)。


另一方面,有專門設計的散列函式允許這樣的事情:分別散列消息的兩個(或更多)部分,並從部分散列創建最終散列。

查看 Wikipedia 中的Merkle 樹文章,它解釋了基本原理。當用作簡單的消息雜湊算法(而不是複雜的結構)時,為了獲得確定性的結果, $ F_1 $ 需要是一些特定值之一(例如 2 的冪),因此之間的限制 $ F_1 $ 和 $ F_2 $ 正好落在兩個子樹之間的邊界上。

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