Published Date : 2021年7月6日13:00

006 Pythonでビットコインを学ぶ (シャー256 ノンス)
006 Use python to learn bitcoin (sha256 nonce)


This blog has an English translation


ニコニコ動画にアップした動画のまとめ記事です。

This is a summary blog post about a video I uploaded to NicoNico.

細かい部分は動画を参考にしてください。

Please refer to the video for details.


目次

Table of Contents




① 動画の説明
① Video Description



前回の続きです。

Continued from last time.

ハッシュ関数を使うと、一文字だけ違う文字でもまったく異なる英数字の文字列が出力されます。

A hash function outputs a completely different alphanumeric string, even if the string differs by only one character.

また、どんなに長い文字列やバイナリでも出力される英数字の文字列の長さは変わりません。

Also, no matter how long a string or binary is, the length of the output alphanumeric string does not change.

よく使われるsha256は256ビットのバイト列を出力します。文字数で言うと64文字です。

The popular sha 256 outputs a 256 bit sequence of bytes. The number of characters displayed is 64.

文字列もメディア情報等もコンピューター内部では同じビット列です。

Both character strings and data such as images and files are processed as bit strings inside the computer.

なので、ソフトウェア等もハッシュ関数を通せば英数字の文字列を出力します。

So if you use a hash function, data such as software and files will be output as alphanumeric strings just like strings.

ではPythonを使って確かめてみましょう。

Let's test it with Python.

まずはhashlibモジュールからmd5,sha1,sha256をインポートします。

First, import md5, sha1, and sha256 from the hashlib module.

from hashlib import md5, sha1, sha256

適当なメッセージを作成します。

First, create a message.

message = "AはBに1BTCを送金する"

md5,sha1,sha2でそれぞれメッセージのハッシュ値を計算します。

Let's compute the hash value of each message using md5, sha1, and sha256.

md5_hash = md5(message.encode()).hexdigest()
sha1_hash = sha1(message.encode()).hexdigest()
sha256_hash = sha256(message.encode()).hexdigest()

元の文字列の長さと、それぞれのハッシュ値、そしてそのハッシュ値の長さを表示してみましょう。

Let's display the length of the original string, each hash value, and the length of the hash value.

print("Message length", len(message))

メッセージは13文字です。

The message is 13 characters long.

md5のハッシュ値は32文字で16進数表記なので16バイトです。

The md5 hash value is 32 characters in hexadecimal notation, so 16 bytes.

print("MD5 hash value length: ", len(md5_hash))

sha1のハッシュ値は40文字で16進数表記なので20バイトです。

The sha1 hash value is 40 characters in hexadecimal notation, so 20 bytes.

print("SHA1 hash value length: ", len(sha1_hash ))

sha256のハッシュ値は64文字で16進数表記なので32バイトです。

The sha256 hash value is 64 characters in hexadecimal notation, so 32 bytes.

print("SHA256 hash value length: ", len(sha256_hash))

ではメッセージを一文字変えてみましょう。

Let's change the message by one letter.

同じ様にハッシュ値を計算してみましょう。

Let's calculate the hash value in the same way.

まったく違うハッシュ値が算出されていることが確認できるはずです。

You should be able to see that a completely different hash value has been computed.

それでは文字数の多いメッセージで同じようにハッシュ値を計算してみましょう。

Let's calculate the hash value in the same way for a long message.

まったく同じ長さのハッシュ値が算出されていることが確認できるはずです。

You should see that a hash value of exactly the same length has been computed.

今度は画像データのハッシュ値を算出してみましょう。

Now let's calculate the hash value of the image data.

image_path = "image.png"
with open(image_path, 'rb') as f:
    image_data = f.read()
    md5_hash_image_data = md5(image_data).hexdigest()
    sha1_hash_image_data = sha1(image_data).hexdigest()
    sha256_hash_image_data = sha256(image_data).hexdigest()

先ほどのメッセージと比べてかなり大きな数字のバイト数になっていますが、算出されたハッシュ値の長さはまったく同じです。

This is a much larger number of bytes than the previous message, but the calculated hash value is exactly the same length.

それでは次はソフトウェアが梱包されている圧縮ファイルのハッシュ値を算出してみましょう。

Now let's calculate the hash value of the compressed file that contains the software.

後で出てきますが、初期のビットコインのソフトウェアをダウンロードして検証の為に使ってみます。

As you will see later, I will download the initial Bitcoin software and use it for verification.

rar_path = "bitcoin-0.1.0.rar"
with open(rar_path, 'rb') as f:
    rar_data = f.read()
    md5_hash_rar_data = md5(rar_data).hexdigest()
    sha1_hash_rar_data = sha1(rar_data).hexdigest()
    sha256_hash_rar_data = sha256(rar_data).hexdigest()

ソフトウェアの場合は、このように予め算出されたハッシュ値が提示されていることが多いです。

In the case of software, a hash value calculated in advance like this is often presented.

これは、1ビットでもファイルの内容が変われば算出されるハッシュ値がまったく異なる数値になるのを利用して、改竄されたソフトウェアではないことを各自で調べることができるようにするためです。

This is because the hash value is completely different if the file contents are changed by even one bit. In other words, you can ensure that the software has not been tampered with.

こちらも先ほどの画像データと比べるととても大きな数字のバイト数になっていますが、算出されたハッシュ値の長さはまったく同じです。

This is also a very large number of bytes compared to the previous image data, but the calculated hash value is exactly the same length.

それではダウンロードした圧縮ファイルやその中身のソフトウェアが改竄されたものでないことを確かめるために、算出されたハッシュ値とダウンロードサイトにあるハッシュ値とを比べてみましょう。

Now compare the calculated hash value with the hash value on the download site to make sure that the compressed file you downloaded and the software in it were not tampered with.

Pythonを使って算出したハッシュ値をコピーして、その値をサイト内で文字検索してみます。

Copy the hash value computed using Python and search for it in your site.

ハッシュ値が一致していることが確認できました。

The hash values were found to match.

偽造を防ぐことはできましたが、次は多重使用の問題がでてきます。

We were able to prevent forgery, but then we have the problem of multiple spending.

多重使用とは本来一回しか使えないコイン等を複数回使用することです。

Multiple spending refers to the repeated use of coins that normally can only be used once.

デジタル上での取引は単なるデータのやり取りに過ぎません。

Digital transactions are just data exchanges.

つまり、一人一人と取引をすると仮定して、AはBやC、D等にそれぞれAの署名付きの送金データを送ります。

In other words, A sends remittance data with A's signature to B, C, D, etc., assuming that each person makes a transaction.

BやCやDにとってはAの署名は本物ですから、全て正しい取引になってしまいます。

As for B, C and D, A's signature is genuine, so all the transactions are correct.

この行為を許すと、Aは一つのコインを無限に使用でき、このコインを使った全体としての取引が成り立たなくなってしまいます。

If this action is allowed, A can use one coin indefinitely, and the entire transaction using this coin will not be possible.

そこで、まずは取引の順番を知る必要がでてきます。一番最初の取引でコインが使われていれば、その後の取引を無効にするということです。

So, first of all, you need to know the order of transactions. It means that if coins are used in the first transaction, the subsequent transactions will be nullified.

その為には全ての取引の記録を皆が確認できるようにすることが重要です。

In order to do so, it is important that everyone can check the records of all transactions.

前回のブロックのハッシュ値と取引をまとめたハッシュ値とノンスと言われる値を合わせてハッシュ値を導きだします。

The hash value is derived by combining the hash value of the previous block, the hash value of the transaction, and the value called nonce.

そしてタイムスタンプ等を含めて、それらをまとめてブロック化します。

It then blocks them together, including the timestamp and the version number of the block, etc.

そのブロックを前回のブロックの後に繋げていきます。

You connect the block after the last block.

ノンスを説明するため、分かりやすく前のブロックのハッシュ値のみを使います。

To illustrate the nonce, I use only the hash value of the previous block for clarity.

そのハッシュ値に適当な数字を加えて、ハッシュ関数に渡して、先頭に0がいくつかつくハッシュ値を求めます。

Add a number to the end of the hash value, pass it to the hash function, and calculate a hash value that begins with several zeros.

まずノンスを0000000にしてみましょう。

First, let's set Nonce to 0000000.

ここでは速くノンスを見つける為、先頭の4桁が0になるハッシュ値を計算してみましょう。

Let's calculate a hash value where the first four digits are 0 to find the nonce faster.

ノンスを51806としてハッシュ値を計算してみましょう。先頭の4桁が0になりません。

Let's calculate the hash value with a nonce of 51806. The first four digits are not zero.

次にノンスを817500としてハッシュ値を計算してみましょう。みごと先頭の4桁が0になりました。

Now let's compute the hash value using a nonce of 817500. The first four digits are now 0.

このようにしてノンスを求めていきます。本来ならゼロの数はもっと多くなります。そうするとかなりの計算量が必要になります。

This is how you look for nonce. The number of zeros would be much more. This requires a lot of computation.

これを複数のノードが競争するように総当たりでノンスを求めて、一番最初にノンスを導き出した人がブロックを繋げることができます。

This is done by multiple nodes in a competition. And the first node to derive the nonce can connect the blocks.



以上です。お疲れ様です。

That's all. Thank you for your hard work.