Pythonの「hashlib」というライブラリを使って、画像ファイルからハッシュ値を生成する方法を備忘録としてまとめます。
なお、私の環境は以下です。
- Python: 3.7.4
目次
ハッシュ値とは?
ハッシュ値とは、以下の図のようにあるInputデータからハッシュ関数によって変換された値です。
ハッシュ値については以下のような特徴があります。
- Inputデータが同じなら、同じハッシュ値が得られる
- Inputデータが異なるなら、異なるハッシュ値が得られる
- ハッシュ値からInputデータを復元できない
- ハッシュ値が重複することは非常に低い
- Inputデータのサイズは任意である
- ハッシュ値のサイズはハッシュ関数によって異なるが固定のサイズである
このように、ハッシュ値はInputデータを他の値に変換させつつ、識別性を持たることができます。
そのため、文字列やファイルなどの同一性チェックに使用することができます。
また、代表的なハッシュ関数は以下のようなものがあります。
ハッシュ関数 | バイト数 | 補足 |
---|---|---|
MD5 | 16 byte | 脆弱性が指摘されている |
sha1 | 20 byte | 脆弱性が指摘されている |
sha256 | 32 byte | |
sha512 | 64byte |
- 詳しくは、「hashアルゴリズムとハッシュ値の長さ一覧」を参照してください。
Pythonでハッシュ値を生成するには?
Pythonでハッシュ値を生成するには「hashlib」というライブラリを使えば簡単にできます。
指定できるハッシュ関数については、以下が対応できます。
※「hashlib.algorithms_guaranteed
」で取得することができます。
- sha1
- shake_128
- sha512
- shake_256
- sha3_512
- md5
- sha384
- blake2b
- sha256
- sha3_384
- blake2s
- sha224
- sha3_256
- sha3_224
サンプルコード
ハッシュ関数のInput値は何でもよいので、テキストでもファイルでもハッシュ値をもとめることができます。
ここでは、この記事のタイトル通り、画像ファイルからハッシュ値を生成するサンプルコードを紹介します。
import hashlib
# png_imgfileとpng_imgfile_samenameは
# ファイル名が違うだけの同一PNGフォーマットの画像ファイル
png_imgfile = 'png_image.png'
png_imgfile_samename = 'png_image_samefile.png'
# jpeg_imgefileはJpegフォーマットの画像ファイル
jpeg_imgefile = 'jpeg_image.JPG'
# png_image.pngについてMD5,SHA256を生成
print('##### {0} #####'.format(png_imgfile))
with open(png_imgfile, 'rb') as f:
md5 = hashlib.md5(f.read()).hexdigest()
f.seek(0)
sha256 = hashlib.sha256(f.read()).hexdigest()
print('MD5ハッシュ値:\n {0}'.format(md5))
print('SHA256ハッシュ値:\n {0}'.format(sha256))
# png_image_samefile.pngについてMD5,SHA256を生成
print('##### {0} #####'.format(png_imgfile_samename))
with open(png_imgfile_samename, 'rb') as f:
md5 = hashlib.md5(f.read()).hexdigest()
f.seek(0)
sha256 = hashlib.sha256(f.read()).hexdigest()
print('MD5ハッシュ値:\n {0}'.format(md5))
print('SHA256ハッシュ値:\n {0}'.format(sha256))
# jpeg_image.JPGについてMD5,SHA256を生成
print('##### {0} #####'.format(jpeg_imgefile))
with open(jpeg_imgefile, 'rb') as f:
md5 = hashlib.md5(f.read()).hexdigest()
f.seek(0)
sha256 = hashlib.sha256(f.read()).hexdigest()
print('MD5ハッシュ値:\n {0}'.format(md5))
print('SHA256ハッシュ値:\n {0}'.format(sha256))
hashlib.ハッシュ関数名()
では、byte-likeオブジェクトの指定が求められたので、open('ファイル名', 'rb')
でバイナリモードとして画像ファイルを読み込むことにしました。f.seek(0)
は、f.read()
によってバイトストリームの位置がファイルの末端に移動してしまうため、ストリームの位置をファイルの先頭に移動するための処理です。- これについては少しハマったので、以下「Python imghdr.what()で画像ファイルのフォーマットを取得できない」でまとめています。
【実行結果】
##### png_image.png #####
MD5ハッシュ値:
41590e74c58948395fc89dc4da3b6a33
SHA256ハッシュ値:
dd939ff23dc8278f010286682e51f198b727237f8f1191a42730ae92effc2273
##### png_image_samefile.png #####
MD5ハッシュ値:
41590e74c58948395fc89dc4da3b6a33
SHA256ハッシュ値:
dd939ff23dc8278f010286682e51f198b727237f8f1191a42730ae92effc2273
##### jpeg_image.JPG #####
MD5ハッシュ値:
00446c46208f8901faeb442631b33f79
SHA256ハッシュ値:
ee8e83be0986d75b62689605ffb9a5f26e78a7da253687b3f5d4d929b87ff496
実行結果を見ると、以下のことが分かります。
- ファイル名が異なるが同じファイルである「png_image.png」と「png_image_samefile.png」のハッシュ値は同じ
- 異なるファイル「png_image.png」と「jpeg_image.JPG」のハッシュ値とは異なる
- PNG、JPEGフォーマットに関係なくハッシュ値を生成できる
関連情報
自分は、PythonをConoHa VPS上に構築しています。構築方法や挑戦したことなどを以下のブログにまとめたので、よろしければご覧になってください。
参考
- hashlib md5やsha256などのハッシュ値を生成する
- hashlib(公式ドキュメント)
- hashアルゴリズムとハッシュ値の長さ一覧
- Pythonの画像読み込み: PIL, OpenCV, scikit-image
広告
Pythonを勉強するなら、Udemyの「現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル」がオススメです!
※Udemyは技術的な講座を動画で受けられるサービスです。
以上!
コメント