ブロックチェーンのセキュリティー対策におけるhash値の活用事例 | Pythonによるhash値の出力方法も紹介

hash値は、特定のルールに従って元のデータを不規則なデータに変換した値のことです。hash値はセキュリティー対策に有用で、ブロックチェーンの改ざん防止にも活用されています。本記事では、hashの概要や、ブロックチェーンのセキュリティー対策事例を解説します。実際にPythonによるhash値の出力方法も紹介しているので、ブロックチェーンのセキュリティー知識に興味のある方はぜひ参考にしてください。

## hash値とは
hash（ハッシュ）値は、あるデータを特定のルールで変換して算出した不規則な英数文字列のことです。`ハッシュ`という言葉は、「切り刻む」という意味で使われることもあり、ハッシュドビーフなどが有名な例として挙げられます。同様のイメージで、一般的なhash値の算出も、元のデータを分割し、それぞれに対して変換処理を行い、再結合するというステップで行われています。

hash値の算出には`MD5`や`RIPEMD-160`、`SHA256`などのアルゴリズムが利用されています。利用するアルゴリズムによって、hash値の算出時間や文字列の長さが異なります。これらのアルゴリズムによって得られるhash値は、後述する特徴を活かしてセキュリティー対策に幅広く活用されています。

## hashの数学的特徴
hash値はいくつかの数学的特徴を持っています。例えば、hash値の算出は容易だが、hash値から元データの復元や推測は困難であるという性質があります。困難さの度合いは利用するアルゴリズムによってことなります。また、元のデータが同じ場合、同じhash値が出力される一方、元のデータが1文字でも異なる場合、hash値は大幅に異なるという特徴もあります。

## Pythonでhash値を出力する方法
具体的なhash値をイメージできるように、Pythonを利用して出力してみましょう。今回は`SHA256`というアルゴリズムを利用します。Python3の実行環境が整っていることが前提です。まずはhash化に必要な`hashlib`ライブラリをインポートします。

```Console
import hashlib
```

次に、hash前の値を`input_data`変数にセットします。ここでは「ちち、ものすごいうそつき。でも、かっこいいうそつき」という文字列からhash値を生成します。hash前の値はバイト型である必要があるため、文字列からバイト型に変換してから変数に代入します。

```Console
input_data = "ちち、ものすごいうそつき。でも、かっこいいうそつき"
input_data_byte = bytes(input_data, encoding = "utf-8")
```

`sha256`メソッドを利用してhash値を出力します。下記のスクリプトを実施すると、hash値がHASHオブジェクト形式で出力されます。

```Console
hashlib.sha256(input_data_byte)
```

以下のような出力結果となります。
[![Image from Gyazo](https://i.gyazo.com/ba6a07783a592f6727e06ddb0960f408.png)](https://gyazo.com/ba6a07783a592f6727e06ddb0960f408)

`hexdigest`メソッドを用いると16進数文字列のhash値を出力できます。下記のスクリプトを実行してください。

```Console
hashlib.sha256(input_data_byte).hexdigest()
```

以下のように不規則な英数文字列が出力されます。元のデータの推測は難しいことが見て取れるでしょう。また実際に、この文字列から元のデータの逆算は非常に困難とされています。
[![Image from Gyazo](https://i.gyazo.com/4c766cc0cb48dc92c8a5d25f1031855b.png)](https://gyazo.com/4c766cc0cb48dc92c8a5d25f1031855b)

もう一度同じデータからhash値を出力して、同じ英数文字列が表示されることを確認してみましょう。

```Console
input_data_2 = "ちち、ものすごいうそつき。でも、かっこいいうそつき"
input_data_2_byte = bytes(input_data_2, encoding = "utf-8")
hashlib.sha256(input_data_2_byte).hexdigest()
```

以下のような出力結果となり、まったく同じhash値が出力されます。
[![Image from Gyazo](https://i.gyazo.com/8270ec85c4ce4e1f6ec53f6c4cc58fc1.png)](https://gyazo.com/8270ec85c4ce4e1f6ec53f6c4cc58fc1)

次は元のデータを1文字変えてhash値を出力し、値が大きく異なることを確認しましょう。

```Console
input_data_3 = "ちち、ものすごくうそつき。でも、かっこいいうそつき"
input_data_3_byte = bytes(input_data_3, encoding = "utf-8")
hashlib.sha256(input_data_3_byte).hexdigest()
```

以下の出力結果となり、hash値が大きく異なることが分かります。
[![Image from Gyazo](https://i.gyazo.com/389743cb4c4c25822a9004f9d8879acf.png)](https://gyazo.com/389743cb4c4c25822a9004f9d8879acf)

ご自身のPCで元のデータを好きなものに変更して試してみてください。hash値についてより詳細に知りたい方は、下記のリンクも参考にしてください。
https://docs.python.org/ja/3/library/hashlib.html#hash-algorithms

## ブロックチェーンにおけるhash値のセキュリティー活用事例
hash値を実際に出力してみることで、具体的なイメージが湧いたと思います。ここではブロックチェーンにおけるhash値のセキュリティー活用事例を、具体的な改ざん防止ロジックとともに解説します。

ブロックチェーンとは複数の取引情報のデータです。複数の取引情報をブロックという単位でまとめ、そのブロックを連結させたチェーンのようなデータ構造を持つため、ブロックチェーンと呼ばれます。ブロックチェーンはその構造上、データの改ざんに強いという特徴があります。前述した数学的特徴を活かし、hash値はブロックチェーンの改ざん防止に活用されています。

[![Image from Gyazo](https://i.gyazo.com/be0cbba46ecfb603d4719049ecf213cf.png)](https://gyazo.com/be0cbba46ecfb603d4719049ecf213cf)


### 各ブロックは直前のブロックのhash値を持つ
ブロックチェーンの各ブロックは、前のブロック情報のhash値を保持しています。この構造によってブロックの前後関係が生まれます。あるブロックの情報を改ざんしようとする場合、そのブロックより後ろのブロックすべてのhash値を再計算する必要性が生まれます。

[![Image from Gyazo](https://i.gyazo.com/36e20d03bab2ba58cdbf89eac7608552.png)](https://gyazo.com/36e20d03bab2ba58cdbf89eac7608552)

※補足：ブロックの構成要素
ブロックチェーンのブロックは一般的に`time`, `transaction`, `hash`, `nonce`という4つの要素を持っています。`time`はブロックの生成時刻、 `transaction`は取引情報、 `hash`は前のブロックのhash値、`nonce`は後述するProof of Workの仕組みに活用される数値です。

### 多数のhash値算出プロセスを経てブロックが生成される
一部のブロックチェーンは、hashの特徴を利用して意図的にブロック生成に時間がかかるような制約があります。この制約と前述した「あるブロックの情報を改ざんしようとする場合、そのブロックより後ろのブロックすべてのhash値を再計算する必要性」によって改ざん防止力を高めています。制約をクリアしてブロックを生成する具体的なステップを記載します。

1.	生成予定のブロックに格納しようとしているtransactionsとhashとnonceの連結データのhash値を算出する。この時のnonce値をまずは0にする。
2.	hash値の頭4桁（この桁数はシステムによって異なる）が全て0であるかを確認する。
3.	全て0ではない場合、次はnonce値を1として、transactionsとhashとnonceの連結データのhash値を算出する。
4.	hash値の頭4桁が全て0であるかを確認する。
5.	nonce値を1ずつ増やしながら、transactionsとhashとnonceの連結データのhash値の頭4桁が全て0となるまで繰り返す。

[![Image from Gyazo](https://i.gyazo.com/1c9b838fd7ddd7dc7cf6a958774e6768.png)](https://gyazo.com/1c9b838fd7ddd7dc7cf6a958774e6768)

hash値から元データを推測することは困難です。そのため、hash値の頭4桁が全て0という条件を満たすためには、少しずつnonce値を変えながらhash値の算出を繰り返す必要があります。hash値の頭4桁が全て0となるようなnonce値を新ブロックに保持させるルールを設けることで、ブロック生成の難易度が高まります。

### ブロックが改ざんされていないことをhash値によって検証する
ブロックチェーンは多くの場合、中央管理者不在で、複数の組織や個人それぞれが同一のブロックチェーンのデータを保持しています。同一のブロックチェーンを共有するデータ同期のプロセスの中で、ブロックが改ざんされていないことを検証する必要があります。この検証にhash値が利用されています。

具体的には、「各ブロックは直前のブロックのhash値を持っているか？」「transactionsとhashとnonceの連結データのhash値の頭4桁が全て0か？」を実際にhash値算出によって検証します。これらの仕組みが、ブロックチェーンはデータ改ざん防止に貢献しています。

## まとめ
hash値は数学的特徴を活かして、セキュリティー対策に利用されています。本記事で紹介した具体的なhash値出力の操作やブロックチェーンでのセキュリティー活用事例を参考に、セキュリティーの仕組みの理解を深めていきましょう。

セキュリティーについて学ぶ際は、セキュリティー単体を学習するよりも、何かのシステムにおけるセキュリティー対策として学ぶ方が楽しく進められるでしょう。ブロックチェーンでもいくつかのセキュリティー対策がなされています。「Pythonによるブロックチェーン開発教本」（私が制作したもの）はブロックチェーンをゼロからプログラミングする学習教材です。ブロックチェーン初学者向けに執筆されています。ブロックチェーン開発を通じてセキュリティーを学びたい方は、ぜひ無料公開の部分からお試しください。

日本語版

https://www.amazon.co.jp/dp/B0B55XSBNZ

英語版

https://www.amazon.co.jp/dp/B0B7BLLDWQ