去,中间状态SHA-256哈希

The*_*chu 3 hash state sha sha256 go

拥有128个字节的数据,例如:

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca064f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d89b574a864db8345b1b00b5ac00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
Run Code Online (Sandbox Code Playgroud)

并且想要在其上执行SHA-256哈希,必须将它分成两个64字节的数据并在将结果一起散列之前单独散列它们.如果要经常更改数据后半部分的某些位,可以简化计算并仅将前半部分数据哈希一次.如何在Google Go中做到这一点?我试着打电话

func SingleSHA(b []byte)([]byte){
    var h hash.Hash = sha256.New()
    h.Write(b)
    return h.Sum()
}
Run Code Online (Sandbox Code Playgroud)

但不是正确的答案

e772fc6964e7b06d8f855a6166353e48b2562de4ad037abc889294cea8ed1070
Run Code Online (Sandbox Code Playgroud)

我有

12E84A43CBC7689AE9916A30E1AA0F3CA12146CBF886B60103AEC21A5CFAA268
Run Code Online (Sandbox Code Playgroud)

比特币论坛上讨论这个问题时,有人提到获得中间状态哈希可能存在一些问题.

如何计算Google Go中的中间状态SHA-256哈希值?

The*_*chu 5

与比特币相关的字节操作有点棘手,因为它们倾向于随心所欲地切换字节序.首先,我们采用初始[]字节数组表示

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca064f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d89b574a864db8345b1b00b5ac00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
Run Code Online (Sandbox Code Playgroud)

然后,我们分离出数组的前半部分,获得:

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca06 4f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d8
Run Code Online (Sandbox Code Playgroud)

在那之后,我们需要交换一些字节.我们在每个4字节的片中反转字节顺序,从而获得:

0100000076C470C5F0B3AD4A9F619598B80090549E781AB575EA587F977000000000000064A03C10396CC7F820F8830614E94330C4FCA76642BC6E0ED8C2BC8F
Run Code Online (Sandbox Code Playgroud)

这就是我们将用于计算中间状态的数组.现在,我们需要更改文件hash.go,添加到type Hash interface:

Midstate() []byte
Run Code Online (Sandbox Code Playgroud)

并更改文件sha256.go,添加此功能:

func (d *digest) Midstate() []byte {
    var answer []byte
    for i:=0;i<len(d.h);i++{
        answer=append(answer[:], Uint322Hex(d.h[i])...)
    }
    return answer
}
Run Code Online (Sandbox Code Playgroud)

Uint322Hex转换一个uint32变量到一个[]byte变量.有了这一切,我们可以打电话:

var h BitSHA.Hash = BitSHA.New()
h.Write(Str2Hex("0100000076C470C5F0B3AD4A9F619598B80090549E781AB575EA587F977000000000000064A03C10396CC7F820F8830614E94330C4FCA76642BC6E0ED8C2BC8F"))
log.Printf("%X", h.Midstate())
Run Code Online (Sandbox Code Playgroud)

Str2Hex把一个string[]byte.结果是:

69FC72E76DB0E764615A858F483E3566E42D56B2BC7A03ADCE9492887010EDA8
Run Code Online (Sandbox Code Playgroud)

记住正确的答案:

e772fc6964e7b06d8f855a6166353e48b2562de4ad037abc889294cea8ed1070
Run Code Online (Sandbox Code Playgroud)

我们可以比较它们:

69FC72E7 6DB0E764 615A858F 483E3566 E42D56B2 BC7A03AD CE949288 7010EDA8
e772fc69 64e7b06d 8f855a61 66353e48 b2562de4 ad037abc 889294ce a8ed1070
Run Code Online (Sandbox Code Playgroud)

所以我们可以看到,我们只需要在4个字节的每个切片中交换一个位的字节,我们将拥有比特币池和矿工使用的正确"中间状态"(直到由于被弃用而不再需要它).