Python3でファイルのハッシュを計算する。

ファイルが同一であるか調べるのに便利です。

## 使い方

[**バイナリデータ**](#バイナリデータ)を指定した[**ハッシュアルゴリズム**](#ハッシュアルゴリズム)で計算し、バイナリの**digest**や16進数の**hexdigest**で取り出すことができます。  

#### 簡単な例
**hashib.アルゴリズム名 ( バイナリデータ ).hexdigest()**

文字列'abc'のmd5を表示します。

~~~python
>>> import hashlib
>>> hashlib.md5(b'abc').hexdigest()
'900150983cd24fb0d6963f7d28e17f72'
~~~

***
#### newを使った例
**new**を使うとアルゴリズムを変えて計算することもできます。
文字列'abc'をMD5とSHA-1で計算し出力します。

~~~python
# モジュールをインポートします
import hashlib

# バイナリデータを用意します
BinaryData = b'abc' 

for i in ('md5','sha1'):
    # ハッシュオブジェクトを作ります
    h = hashlib.new( i)

    # バイナリデータからハッシュを計算します
    h.update(BinaryData)

    # ハッシュオブジェクトを16進数で出力します
    print( i, h.hexdigest())
~~~
結果

~~~
md5 900150983cd24fb0d6963f7d28e17f72
sha1 a9993e364706816aba3e25717850c26c9cd0d89d
~~~

***
#### 分割して計算する例
データサイズが大きすぎる場合は**update**を使います。
この例では分割して計算しても出力が同じになることを確認できます。

~~~python
# モジュールをインポートします
import hashlib

# 大きなバイナリデータを用意します
BigBinaryData = b'abcd'*0x100000

# ハッシュアルゴリズムを決めます
algo = 'md5'

# 分割せずにハッシュを計算する
h = hashlib.new(algo)
h.update(BigBinaryData)
print(algo,h.hexdigest())

# ハッシュオブジェクトを作ります
h = hashlib.new(algo)

# 分割する長さをブロックサイズの整数倍に決めます
Length = hashlib.new(algo).block_size * 4096

# データがある間ループします
while BigBinaryData:
    
    # 計算に使用する部分を取り出します
    BinaryData = BigBinaryData[:Length]
    
    # 取り出した部分を切り離して捨てます
    BigBinaryData = BigBinaryData[Length:]

    # ハッシュオブジェクトに追加して計算します。
    h.update(BinaryData)
    
# ハッシュオブジェクトを16進数で出力します
print(algo,h.hexdigest())
~~~
結果

~~~
md5 cf3598e0d72fbed531070afd240c76b9
md5 cf3598e0d72fbed531070afd240c76b9
~~~

***
#### 巨大なファイルのハッシュ
メモリに読み込めないほど巨大なファイルは分割して計算します。

~~~python
# モジュールをインポートします
import hashlib

# ハッシュアルゴリズムを決めます
algo = 'md5'

# ハッシュオブジェクトを作ります
h = hashlib.new(algo)

# 分割する長さをブロックサイズの整数倍に決めます
Length = hashlib.new(algo).block_size * 0x800

# 大きなバイナリデータを用意します
path = 'test.zip'
with open(path,'rb') as f:
    BinaryData = f.read(Length)

    # データがなくなるまでループします
    while BinaryData:
    
        # ハッシュオブジェクトに追加して計算します。
        h.update(BinaryData)

        # データの続きを読み込む
        BinaryData = f.read(Length)

# ハッシュオブジェクトを16進数で出力します
print(algo,h.hexdigest())
~~~
結果

~~~
md5 58c647b74f394f1cadef669607f59ab8
~~~
フリーソフトの**[WinMD5 Free](http://www.winmd5.com/)**でも同一の結果が得られました。


<br>
***
#### バイナリデータ
文字列やファイルをバイナリデータとして扱います

~~~python
# 文字列(str)をバイナリデータ(bytes)に変換する。
>>> BinaryData = b'abc'

# 文字列(str)をバイナリデータ(bytes)にエンコードする。
>>> BinaryData = 'abc'.encode('UTF-8')

# ファイルをバイナリモードで読み込む
>>> with open('test.txt','rb') as f:
        BinaryData = f.read()
~~~


<br>
***
#### ハッシュアルゴリズム

利用できるアルゴリズム名は**algorithms_guaranteed**や**algorithms_available**で確認できます。

~~~python
# すべてのプラットフォームで使えるもの
>>> hashlib.algorithms_guaranteed
{'blake2s', 'sha256', 'sha224', 'sha512', 'sha1', 'sha3_256', 'blake2b', 'shake_128', 'sha3_512', 'md5', 'sha3_224', 'sha384', 'shake_256', 'sha3_384'}

# 利用中のプラットホームで使えるもの
>>> hashlib.algorithms_available
{'blake2s', 'md4', 'sha512', 'sha3_256', 'whirlpool', 'blake2b', 'blake2s256', 'sha3_512', 'md5', 'sha384', 'md5-sha1', 'sha3_384', 'mdc2', 'ripemd160', 'sha256', 'sha224', 'shake_128', 'sha3_224', 'sha1', 'shake_256', 'blake2b512'}
~~~


<br><br>
-参考-  
[hashlib --- セキュアハッシュおよびメッセージダイジェスト — Python 3.7.4 ドキュメント](https://docs.python.org/ja/3/library/hashlib.html)