2012-02-12 7 views
3

は、128バイトのデータを有する、例えば:進み、midstate SHA-256ハッシュ

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca064f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d89b574a864db8345b1b00b5ac00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000 

、その上にSHA-256ハッシュを実行したい、一つはデータの2つの64バイトに分離しなければならないと結果を一緒にハッシュする前にそれらを個別にハッシュします。データの後半でビットを頻繁に変更する場合は、計算を単純化し、データの前半を1回だけハッシュすることができます。 Google Goでそれをどうやって行いますか?私は誰かがいることを取得していくつかの問題があるかもしれないと述べ、

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

しかし、その代わりにBitcoin forum上の問題を議論するとき、私は

12E84A43CBC7689AE9916A30E1AA0F3CA12146CBF886B60103AEC21A5CFAA268 

を得た

e772fc6964e7b06d8f855a6166353e48b2562de4ad037abc889294cea8ed1070 

適切な答えのを呼び出してみました中期ハッシュ

Google GoでMidstate SHA-256ハッシュを計算するにはどうすればよいですか?

+1

Go 1.0.3では、Sumはバイトスライスを取るので、 'h.Sum([byte]}'を返さなければなりません。 – emicklei

+3

'h.Sum(nil)'も有効です@emicklei: ) – elimisteve

答えて

5

Bitcoin関連のバイト操作は、気まぐれでエンディアンを切り替える傾向があるため、少しトリッキーです。まずの、私たちはその後

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca064f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d89b574a864db8345b1b00b5ac00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000 

を表す最初の[]バイト配列を取る、我々は取得、配列の最初の半分を分離:その後

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca06 4f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d8 

を、私たちは周りにいくつかのバイトをスワップする必要があります。我々はthusly取得、4バイトのすべてのスライスでバイトの順序を逆:

0100000076C470C5F0B3AD4A9F619598B80090549E781AB575EA587F977000000000000064A03C10396CC7F820F8830614E94330C4FCA76642BC6E0ED8C2BC8F 

そして、それは我々がmidstateを計算するために使用される配列です。

Midstate() []byte 

を、この機能を追加し、ファイルsha256.goを変更:今、私たちはtype Hash interfaceへの追加、ファイルhash.goを変更する必要がUint322Hex[]byte変数にuint32変数を変換し

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 
} 

。すべてのことを持って、我々は呼び出すことができます。Str2Hex[]bytestringをオン

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

を。結果は次のとおりです。

適切な答えを思い出し
69FC72E76DB0E764615A858F483E3566E42D56B2BC7A03ADCE9492887010EDA8 

e772fc6964e7b06d8f855a6166353e48b2562de4ad037abc889294cea8ed1070 

を私たちはそれらを比較することができます

69FC72E7 6DB0E764 615A858F 483E3566 E42D56B2 BC7A03AD CE949288 7010EDA8 
e772fc69 64e7b06d 8f855a61 66353e48 b2562de4 ad037abc 889294ce a8ed1070 

だから我々は、我々は少しだけ周りのバイトをスワップする必要があることがわかりますBitcoinのプールと鉱夫によって使用される適切な "中間状態"を持っています(廃止予定のために必要なくなるまで)。

+0

は、あなたが行く知らない誰かのために '0100000076C470C5F0B3AD4A9F619598B80090549E781AB575EA587F977000000000000064A03C10396CC7F820F8830614E94330C4FCA76642BC6E0ED8C2BC8F'から69FC72E76DB0E764615A858F483E3566E42D56B2BC7A03ADCE9492887010EDA8''に行ってきましたどのように起草気にしませんか? 16進数(文字列16進数から16進数へ変換されたもの)を反復処理していて、符号なしのintで何かをやって、16進数に変換しているようです。 intsがどこから来ているのか、あなたがそれらを使って何をやっているのかは分かりません。どんな助けもありがとう! – JacobEvelyn

+0

@ConstableJoe申し訳ありませんが、私はいくつかの魔法がSHAアルゴリズムによって内部的に行われるかもしれないと心配しています。しかも、これと一緒に遊んでからずっとずっとでした。私は16進配列をWrite関数に入れてSHAにロードします。このアルゴリズムは、Write関数の数値を切り詰めて、符号なし整数の配列に格納します。私はその値を得て、それらをヘクスの配列に変えます。私はそうだと思います。 – ThePiachu

+0

助けてくれてありがとう。私は嫌がらせを続けます。 – JacobEvelyn

3

あなたが持っているGoコードは、バイトストリームのsha256を計算する正しい方法です。

おそらく答えは、あなたがしたいことがsha256ではないということです。具体的には:

結果をハッシュする前に、2つの64ビットのデータに分割して個別にハッシュする必要があります。データの後半でビットを頻繁に変更する場合は、計算を単純化し、データの前半を1回だけハッシュすることができます。

は、sha256を計算するための有効な方法ではありません(たとえば、sha256は、埋め込まれている必要があるデータのブロックに対してその作業を行います)。

説明したアルゴリズムは何かを計算しますが、sha256は計算しません。

予想される値を知っているので、おそらく別の言語でアルゴリズムの参照実装があるので、行単位のポートだけを実行してください。

最後に、それはどんな場合でも疑わしい最適化です。 128ビットは16バイトです。ハッシングコストは、通常、データのサイズに比例します。 16バイトでは、コストが非常に小さいので、8バイトのパーツでデータを分割することで賢明にしようとすると、保存したものよりもコストがかかる可能性があります。

+0

申し訳ありませんが、私はバイトではなく、ビットを意味しました。このデータを使用するインプリメンテーションは、データをハッシュして文字列の後半部分を変更するためのものです。そのため、中間状態を計算すると計算タスクのかなりの部分が節約されます。 – ThePiachu

+0

私は "かなりの部分"をベンチマークします。私にとって、64対128バイトは、特にsha256がどのように機能するかを考えると、重要ではありません。 Sha256は最小56バイトのブロックで動作します。 128バイトで順次sha256を実行する代わりに、データの半分のsha256に対して32バイト(32ビットはsha256チェックサムのサイズ)のオーバーヘッドを加えた64バイト(2 * 56すなわち112にパディング)追加のsha256プロセスを設定します。実際には、128バイトで実行する方が高速です(結果は同等です)。 –

2

sha256.goでは、機能の開始時にSum()が実装され、SHA256状態のコピーが作成されています。基本的なSHA256のデータ型(struct digest)はsha256パッケージ専用です。

私はsha256.goファイルの小さなコピーを作成することをお勧めします(小さなファイルです)。その後、ダイジェストの現在の状態を保存するためにCopy()機能を追加します。

func (d *digest) Copy() hash.Hash { 
    d_copy := *d 
    return &d_copy 
} 

その後、単にmidstate SHA256ハッシュを保存するためにCopy()関数を呼び出します。

+0

コードをコンパイルしてテストしましたか? – peterSO

+0

@peterSO:どういう意味ですか? –

+0

実際には、hash.goファイルを変更してhash.Hashインターフェイスを変更してCopy()を呼び出せるようにする必要がありますが、その後も[BE7E1F35 A19D5938 D8E6A17B 6BDF4738 603BB417 9AE97BCE FAED662 C11CB2F7]という結果が得られます。 – ThePiachu

0

Intel i5 2.70 GHz CPUを使用して、128バイトのデータに対して2つのGoベンチマークを実行しました。最初に、1,000回、私はSHA256ハッシュに128バイトすべてを書き込んで、合計で約9,285,000ナノ秒を要しました。次に、最初の64バイトをSHA256ハッシュに1回書いた後、1,000回、SHA256ハッシュのコピーに2番目の64バイトを書き込んで総計で約6,492,371ナノ秒を要しました。最初の64バイトが不変であると仮定した2番目のベンチマークは、最初のベンチマークより30%少ない時間で実行されました。

最初の方法を使用すると、高速なCPUを購入する前に、1日あたり約9,305,331,179 SHA256 128バイトの合計を計算できます。 2番目の方法を使用すると、より高速なCPUを購入する前に、最初の64バイトが1,000回連続して不変であると仮定して、1日あたり13,307,927,103 SHA256 128バイトの合計を計算できます。 1日に128バイトのSHA256をいくつ計算すればよいですか?最初の64バイトは不変で、1日のSHA256 128バイトの合計数はいくつですか?

実行したベンチマークと結果は何ですか?

+0

私は主にここでトピックの返信を行っています - https://bitcointalk.org/index.php?topic=51281.msg612224#msg612224一般的に、この実装はBitcoinマイニング、特にネットワークプロトコル(リンクされたトピックでも説明されています)に関連しています。それがクライアント側で使用され、GoサポートされているOpenCLの場合、操作の順序は、1秒あたり10^9ハッシュのオーダーである可能性があります(現在のマイニングソフトウェアの速度に達した場合) - https://en.bitcoin。 it/wiki/Mining_hardware_comparison#Multi-Card_Setups。 – ThePiachu

関連する問題