Hash

Merkle 樹中的連接

  • December 20, 2021

考慮一個帶有葉子alice +100和的簡單 Merkle 樹bob +50。使用 SHA256 雜湊算法,各個字元串的摘要為:

# alice +100
dc2cac4a8aaeccc0199eeb77df68b22eaa6e319d3f2b425d078dbd73419e28ac

# bob +50
7e15e5bc1b84f458db7ced4df762ba70204f19e3a613738756f9b00653f0aee1

作為一個雜湊函式,SHA-256 是確定性的,所以我們用哪種程式語言實現它並不重要。為了完整起見,這可以通過crypto-js庫來完成:

const hash256 = (string) => {
 const val = 
 require('crypto').createHash('sha256').update(string).digest('hex');
 return val;
}

# apply
hash256('alice +100')
# results:
dc2cac4a8aaeccc0199eeb77df68b22eaa6e319d3f2b425d078dbd73419e28ac

當提到Merkle Tree 實現時,可以看到以下描述:

散列樹是散列樹,其中的葉子是數據塊的散列,例如,一個文件或一組文件。樹中更遠的節點是它們各自子節點的雜湊值。比如上圖中,hash 0 就是 hash 0-0 和 hash 0-1 串聯的結果。也就是說,hash 0 = hash( hash(0-0) + hash(0-1) ) 其中+表示連接。

在此處輸入圖像描述

我已經看到在 的情況下實現這種連接的更高級別的庫抽象Buffer.concat(),但我想知道從純數學的角度來看,究竟如何實現這一點。

有人會假設(錯誤地):

alice_hash = hash256('alice +100')
bob_hash = hash256('bob +50')
# wrong
hash256(alice_hash + bob_hash)
# wrong also: adding the 0x-prefix
hash256(
 '0xdc2cac4a8aaeccc0199eeb77df68b22eaa6e319d3f2b425d078dbd73419e28ac'
 + 
 '0x7e15e5bc1b84f458db7ced4df762ba70204f19e3a613738756f9b00653f0aee1' 
)

因此,如果沒有任何抽象,如何連接兩個雜湊以獲得結果父節點?

對於任何試圖提供幫助的人, hash(hash(alice) + hash(bob)) 的正確值應該是edf9a9a0e56b58fc9caccb97d85c628d5b9dc50cb94dfc41e83026d37704400f. 我嘗試添加/刪除0x前綴,在它們之間添加一個空格字元,但這些嘗試都沒有結果。我還閱讀了我可以得到的論文,但沒有比“連接它們以獲取父節點的值”更遠,幾乎沒有實現參考。

手頭的問題源於將雜湊值的十六進製字元串表示(‘hexdigest’)與其實際二進制值混合。

首先回想一下,散列函式將任意長度(出於實際目的)的位串作為輸入,並輸出一個固定長度的位串。也就是說,它對二進制值進行操作。

因此,(ASCII 編碼)輸入字元串的實際散列值alice +100是 32 個字節的序列。dc2cac4a8aaeccc0199eeb77df68b22eaa6e319d3f2b425d078dbd73419e28ac是表示為“hexdigest”的字節序列,其中每兩個十六進製字元編碼一個字節。

對於連接操作,您必須連接字節序列,而不是它們的十六進制摘要。

Ruby 中的一個範例:

require 'digest'

m1 = 'alice +100'
m2 = 'bob +50'

d1 = Digest::SHA256.new
d2 = Digest::SHA256.new

d1 << m1
d2 << m2

puts "Alice hexdigest: #{ d1.hexdigest }"
puts "Bob hexdigest: #{ d2.hexdigest }"

d3 = Digest::SHA256.new
d3 << d1.digest
d3 << d2.digest                                                                                                                                                

puts "Concatenation hexdigest: #{ d3.hexdigest }"

執行時會產生:

Alice hexdigest: dc2cac4a8aaeccc0199eeb77df68b22eaa6e319d3f2b425d078dbd73419e28ac
Bob hexdigest: 7e15e5bc1b84f458db7ced4df762ba70204f19e3a613738756f9b00653f0aee1
Concatenation hexdigest: edf9a9a0e56b58fc9caccb97d85c628d5b9dc50cb94dfc41e83026d37704400f

在您的範例中,當您計算兩個十六進製字元串連接的雜湊值時,您的程式語言會連接這兩個字元串,將它們編碼為二進制序列(使用它預設的任何字元編碼),並對輸入序列進行雜湊處理。

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