14.1. hashlib --- セキュアハッシュおよびメッセージダイジェスト

バージョン 2.5 で追加.

ソースコード: Lib/hashlib.py


このモジュールは、セキュアハッシュやメッセージダイジェスト用のさまざまなアルゴリズムを実装したものです。FIPSのセキュアなハッシュアルゴリズムである SHA1、SHA224、SHA256、SHA384およびSHA512 (FIPS 180-2 で定義されているもの) だけでなくRSAのMD5アルゴリズム (Internet RFC 1321 で定義されています)も実装しています。「セキュアなハッシュ」と「メッセージダイジェスト」はどちらも同じ意味です。古くからあるアルゴリズムは「メッセージダイジェスト」と呼ばれていますが、最近は「セキュアハッシュ」という用語が用いられています。

注釈

adler32 や crc32 ハッシュ関数は zlib モジュールで提供されています。

警告

幾つかのアルゴリズムはハッシュの衝突に弱いことが知られています。最後の "参考" セクションを見てください。

hash の名前が付いたコンストラクタがあります。いずれも同一で簡単なインターフェイスのあるハッシュオブジェクトを返します。例えば、SHA1 ハッシュオブジェクトを作るには sha1() を使います。このオブジェクトには update() を用いて任意の文字列を渡すことが出来ます。digest()hexdigest() メソッドを用いて、それまでに渡したデータを連結したものの digest をいつでも要求することが出来ます。

このモジュールで常に使用できるハッシュアルゴリズムのコンストラクタは md5()sha1()sha224()sha256()sha384() および sha512() です。それ以外のアルゴリズムが使用できるかどうかは、Python が使用している OpenSSL ライブラリに依存します。

たとえば、'Nobody inspects the spammish repetition' というバイト文字列のダイジェストを取得するには次のようにします:

>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("Nobody inspects")
>>> m.update(" the spammish repetition")
>>> m.digest()
'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9'
>>> m.digest_size
16
>>> m.block_size
64

もっと簡潔に書くと、このようになります:

>>> hashlib.sha224("Nobody inspects the spammish repetition").hexdigest()
'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'

一般的な new() コンストラクタで、第一引数にアルゴリズム名を文字列で受け取ります。他にも、上記ハッシュだけでなく OpenSSL ライブラリーが提供するような他のアルゴリズムにアクセスすることが出来ます。名前のあるコンストラクタの方が new() よりもずっと速いので望ましいです。

new() にOpenSSLのアルゴリズムを指定する例です:

>>> h = hashlib.new('ripemd160')
>>> h.update("Nobody inspects the spammish repetition")
>>> h.hexdigest()
'cc4a5ce1b3df48aec5d22d1f16b894a0b894eccc'

このモジュールは以下の定数属性を提供しています:

hashlib.algorithms

このモジュールによってサポートされていることが保証されるハッシュアルゴリズムの名前が入ったタプル。

バージョン 2.7 で追加.

hashlib.algorithms_guaranteed

このモジュールによってすべてのプラットフォームでサポートされていることが保証されるハッシュアルゴリズムの名前を含む集合です。

バージョン 2.7.9 で追加.

hashlib.algorithms_available

実行中の Python インタープリタで利用可能なハッシュアルゴリズム名の set です。これらの名前は new() に渡すことが出来ます。algorithms_guaranteed は常にサブセットです。この set の中に同じアルゴリズムが違う名前で複数回現れることがあります (OpenSSL 由来)。

バージョン 2.7.9 で追加.

コンストラクタが返すハッシュオブジェクトには、次のような定数属性が用意されています:

hash.digest_size

生成されたハッシュのバイト数。

hash.block_size

内部で使われるハッシュアルゴリズムのブロックのバイト数。

ハッシュオブジェクトには次のようなメソッドがあります:

hash.update(arg)

文字列 arg でハッシュオブジェクトを更新します。繰り返し呼び出すことは引数全ての連結で一回呼び出すことと等価です。例えば m.update(a); m.update(b)m.update(a+b) と等価です。

バージョン 2.7 で変更: ハッシュアルゴリズムが OpenSSL によって提供されていて、データが 2048 バイトを超えている場合には、ハッシュの更新が実行中でも他のスレッドが実行出来るように、Python GIL が解放されます。

hash.digest()

これまでに update() メソッドに渡した文字列のダイジェストを返します。これは digest_size バイトの文字列であり、非ASCII文字やnull バイトを含むこともあります。

hash.hexdigest()

digest() と似ていますが、倍の長さの、16進形式文字列を返します。これは、電子メールなどの非バイナリ環境で値を交換する場合に便利です。

hash.copy()

ハッシュオブジェクトのコピー ("クローン") を返します。これは、共通部分を持つ複数の文字列のダイジェストを効率的に計算するために使用します。

14.1.1. 鍵導出

鍵の導出【derivation】と引き伸ばし【stretching】のアルゴリズムはセキュアなパスワードのハッシュ化のために設計されました。 sha1(password) のようなうぶなアルゴリズムは、ブルートフォース攻撃への抵抗者にはなりません。良いパスワードハッシュ化は調節可能で、遅くて、 salt を含まなければなりません。

hashlib.pbkdf2_hmac(name, password, salt, rounds, dklen=None)

この関数は PKCS#5 のパスワードに基づいた鍵導出関数 2 を提供しています。疑似乱数関数として HMAC を使用しています。

文字列 name は、HMAC のハッシュダイジェストに使いたいアルゴリズムの名前で、例えば 'sha1' や 'sha256' です。 passwordsalt はバイト列のバッファとして解釈されます。アプリケーションとライブラリは password に相応しい値 (例えば 1024) に制限すべきです。 saltos.urandom() のような適切な所源から得た、およそ 16 かそれよりも多いバイト列でなければなりません。

rounds 数はハッシュアルゴリズムと計算機の能力に基いて決められるべきです。2013 年現在の場合、 SHA-256 に対して最低でも 100,000 ラウンドをお奨めします。

dklenNone の場合、ハッシュアルゴリズム name のダイジェストサイズが使われます。例えば SHA-512 では 64 です。

>>> import hashlib, binascii
>>> dk = hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 100000)
>>> binascii.hexlify(dk)
b'0394a2ede332c9a13eb82e9b24631604c31df978b4e2f0fbd2c549944f9d79a5'

バージョン 2.7.8 で追加.

注釈

pbkdf2_hmac の高速な実装は OpenSSL 使用版で利用可能です。Python 実装は hmac のインラインバージョンを使います。それはおよそ 3 倍遅く、GIL を解放しません。

参考

hmac モジュール
ハッシュを用いてメッセージ認証コードを生成するモジュールです。
base64 モジュール
バイナリハッシュを非バイナリ環境用にエンコードするもうひとつの方法です。
http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
FIPS 180-2 のセキュアハッシュアルゴリズムについての説明。
https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%AD%A6%E7%9A%84%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E9%96%A2%E6%95%B0
どのアルゴリズムにどんな既知の問題があって、それが実際に利用する際にどう影響するかについての Wikipedia の記事。