hashlib --- セキュアハッシュとメッセージダイジェスト¶
ソースコード: Lib/hashlib.py
このモジュールは、多くの異なるハッシュアルゴリズムに共通のインターフェースを実装しています。 FIPS のセキュアハッシュアルゴリズム SHA224、SHA256、SHA384、SHA512 (the FIPS 180-4 standard で定義)、SHA-3 系列 (the FIPS 202 standard で定義)、および旧来の SHA1 (formerly part of FIPS) と MD5 (インターネット RFC 1321 で定義) が含まれます。
注釈
adler32 や crc32 ハッシュ関数は zlib モジュールで提供されています。
ハッシュアルゴリズム¶
各 hash の名前が付いたコンストラクタがあります。いずれも同一で簡単なインターフェイスのあるハッシュオブジェクトを返します。例えば、SHA-256 ハッシュオブジェクトを作るには sha256() を使います。このオブジェクトには update メソッドを用いて bytes-like オブジェクト (通常 bytes) を渡すことができます。digest() や hexdigest() メソッドを用いて、それまでに渡したデータを連結したものの digest をいつでも要求することができます。
複数のスレッドを動作させるため、コンストラクタまたは .update メソッドに一度に 2047 バイトを超えるデータを渡すと、ハッシュの計算中は Python の GIL を解放します。
このモジュールに常に含まれるハッシュアルゴリズムのコンストラクタは、md5()、sha1()、sha224()、sha256()、sha384()、sha512()、sha3_224()、sha3_256()、sha3_384()、sha3_512()、shake_128()、shake_256()、blake2b()、blake2s() です。
これらは algorithms_guaranteed に対応します。
ただし、まれに見られる「FIPS 準拠」の Python ビルドや、OpenSSL の「FIPS モード」でデフォルトのプロバイダから一部のアルゴリズムを除外する設定など、通常と異なる環境では、これらのいずれも欠けていたり使用を制限されていたりする場合があります。
利用できないアルゴリズムのコンストラクタを呼び出すと ValueError を送出します。
使用している Python ディストリビューションの hashlib が、ほかのアルゴリズムを提供する OpenSSL ビルドにリンクされている場合は、それらも利用できることがあります。
これらは すべての環境での利用が保証されているわけではなく、new() に名前を渡す方法でのみアクセスできます。
algorithms_available を参照してください。
警告
一部のアルゴリズム (MD5 と SHA1 を含む) には、ハッシュの衝突に関する既知の弱点があります。 Attacks on cryptographic hash algorithms と、このドキュメントの末尾の hashlib-seealso 節を参照してください。
Added in version 3.6: SHA3 (Keccak) と SHAKE のコンストラクタ sha3_224()、sha3_256()、sha3_384()、sha3_512()、shake_128()、shake_256() が追加されました。
blake2b() と blake2s() も追加されました。
バージョン 3.9 で変更: hashlib のすべてのコンストラクタが、デフォルト値 True のキーワード専用引数 usedforsecurity を受け取るようになりました。
偽の値を指定すると、制限のある環境で、安全でないアルゴリズムや使用を制限されたハッシュアルゴリズムを使えます。
False は、例えば暗号用途でない一方向圧縮関数として使う場合など、そのハッシュアルゴリズムをセキュリティ目的で使わないことを示します。
バージョン 3.9 で変更: OpenSSL が SHA3 と SHAKE を提供する場合、hashlib はそれらを使うようになりました。
バージョン 3.12 で変更: MD5、SHA1、SHA2、SHA3 の各アルゴリズムを、リンク先の OpenSSL が提供していない場合は、HACL* project の検証済み実装にフォールバックするようになりました。
バージョン 3.15 で非推奨、バージョン 3.19 で削除予定: _hashlib.new() と _md5.md5() などのハッシュ名を持つコンストラクタで、ドキュメントに記載されていないキーワード引数 string が非推奨になりました。
後方互換性を最大限に保つには、初期データを位置引数として渡してください。
使用法¶
b"Nobody inspects the spammish repetition" というバイト文字列のダイジェストを取得するには次のようにします:
>>> import hashlib
>>> m = hashlib.sha256()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'
>>> m.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
もっと簡潔に書くと、このようになります:
>>> hashlib.sha256(b"Nobody inspects the spammish repetition").hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
コンストラクタ¶
- hashlib.new(name, [data, ]*, usedforsecurity=True)¶
一般的なコンストラクタで、第一引数にアルゴリズム名を文字列 name で受け取ります。他にも、前述のハッシュアルゴリズムだけでなく OpenSSL ライブラリーが提供するような他のアルゴリズムにアクセスすることができます。
new() にアルゴリズム名を渡す例です。
>>> h = hashlib.new('sha256')
>>> h.update(b"Nobody inspects the spammish repetition")
>>> h.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
- hashlib.md5([data, ]*, usedforsecurity=True)¶
- hashlib.sha1([data, ]*, usedforsecurity=True)¶
- hashlib.sha224([data, ]*, usedforsecurity=True)¶
- hashlib.sha256([data, ]*, usedforsecurity=True)¶
- hashlib.sha384([data, ]*, usedforsecurity=True)¶
- hashlib.sha512([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_224([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_256([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_384([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_512([data, ]*, usedforsecurity=True)¶
このような名前付きコンストラクタは、new() にアルゴリズム名を渡すより高速です。
属性¶
hashlib は次の定数をモジュール属性として提供します。
- hashlib.algorithms_guaranteed¶
このモジュールによってすべてのプラットフォームでサポートされていることが保証されるハッシュアルゴリズムの名前を含む集合です。一部のアップストリームのベンダーが提供する奇妙な "FIPS準拠の" Pythonビルドではmd5のサポートを除外していますが、その場合であっても 'md5' がリストに含まれることに注意してください。
Added in version 3.2.
- hashlib.algorithms_available¶
実行中の Python インタープリタで利用可能なハッシュアルゴリズム名の set です。これらの名前は
new()に渡すことができます。algorithms_guaranteedは常にサブセットです。この set の中に同じアルゴリズムが違う名前で複数回現れることがあります (OpenSSL 由来)。Added in version 3.2.
ハッシュオブジェクト¶
コンストラクタが返すハッシュオブジェクトには、次のような定数属性が用意されています:
- hash.digest_size¶
生成されたハッシュのバイト数。
- hash.block_size¶
内部で使われるハッシュアルゴリズムのブロックのバイト数。
ハッシュオブジェクトには次のような属性があります:
- hash.name¶
このハッシュの正規名です。常に小文字で、
new()の引数として渡してこのタイプの別のハッシュを生成することができます。バージョン 3.4 で変更: name 属性は CPython には最初からありましたが、Python 3.4 までは正式に明記されていませんでした。そのため、プラットフォームによっては存在しないかもしれません。
ハッシュオブジェクトには次のようなメソッドがあります:
- hash.update(data)¶
hash オブジェクトを bytes-like object で更新します。このメソッドの呼出しの繰り返しは、それらの引数を全て結合した引数で単一の呼び出しをした際と同じになります。すなわち
m.update(a); m.update(b)はm.update(a + b)と等価です。
- hash.digest()¶
これまで
update()メソッドに渡されたデータのダイジェスト値を返します。これはdigest_sizeと同じ長さの、0 から 255 の範囲全てを含み得るバイトの列です。
- hash.copy()¶
ハッシュオブジェクトのコピー ("クローン") を返します。これは、最初の部分文字列が共通なデータのダイジェストを効率的に計算するために使用します。
SHAKE 可変長ダイジェスト¶
- hashlib.shake_128([data, ]*, usedforsecurity=True)¶
- hashlib.shake_256([data, ]*, usedforsecurity=True)¶
shake_128() と shake_256() アルゴリズムは、可変長のダイジェストを提供します。
安全性の強度は、ビット単位のダイジェスト長の半分 (length_in_bits//2) で、それぞれ最大 128 ビットまたは 256 ビットです。
そのため、これらの digest() メソッドには長さの指定が必要です。
SHAKE アルゴリズム自体には長さの上限はありません。
- shake.digest(length)¶
これまで
update()メソッドに渡されたデータのダイジェスト値を返します。これは length と同じ長さの、0 から 255 の範囲全てを含み得るバイトの列です。
使用例:
>>> h = hashlib.shake_256(b'Nobody inspects the spammish repetition')
>>> h.hexdigest(20)
'44709d6fcb83d92a76dcb0b668c98e1b1d3dafe7'
ファイルのハッシュ化¶
hashlib モジュールは、ファイルやファイルに似たオブジェクトのハッシュを効率よく計算するための補助関数を提供します。
- hashlib.file_digest(fileobj, digest, /)¶
ファイルオブジェクトの内容で更新されたダイジェストオブジェクトを返します。
fileobj はバイナリモードで読み取り用に開かれた、ファイルに似たオブジェクトでなければなりません。 組み込みの
open()が返すファイルオブジェクト、BytesIOインスタンス、socket.socket.makefile()が返す SocketIO オブジェクトなどを受け付けます。 fileobj はブロッキングモードで開いておく必要があり、そうでなければBlockingIOErrorが送出される場合があります。この関数は Python の I/O を経由せず、
fileno()から得たファイル記述子を直接使う場合があります。 この関数が値を返したり例外を送出したりした後の fileobj の状態は、不明なものとして扱ってください。 fileobj を閉じるのは呼び出し側の責任です。digest には、str で表したハッシュアルゴリズム名、ハッシュのコンストラクタ、ハッシュオブジェクトを返す呼び出し可能オブジェクトのいずれかを指定する必要があります。
例:
>>> import io, hashlib, hmac >>> with open("library/hashlib.rst", "rb") as f: ... digest = hashlib.file_digest(f, "sha256") ... >>> digest.hexdigest() '...'
>>> buf = io.BytesIO(b"somedata") >>> mac1 = hmac.HMAC(b"key", digestmod=hashlib.sha512) >>> digest = hashlib.file_digest(buf, lambda: mac1)
>>> digest is mac1 True >>> mac2 = hmac.HMAC(b"key", b"somedata", digestmod=hashlib.sha512) >>> mac1.digest() == mac2.digest() True
Added in version 3.11.
バージョン 3.14 で変更: ファイルが非ブロッキングモードで開かれている場合は
BlockingIOErrorを送出するようになりました。 以前は、余分なヌルバイトがダイジェストの計算に加わっていました。
鍵導出¶
鍵の導出 (derivation) と引き伸ばし (stretching) のアルゴリズムはセキュアなパスワードのハッシュ化のために設計されました。 sha1(password) のような甘いアルゴリズムは、ブルートフォース攻撃に抵抗できません。良いパスワードハッシュ化は調節可能で、遅くて、 salt を含まなければなりません。
- hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)¶
この関数は PKCS#5 のパスワードに基づいた鍵導出関数 2 を提供しています。疑似乱数関数として HMAC を使用しています。
文字列 hash_name は、HMAC のハッシュダイジェストアルゴリズムの望ましい名前で、例えば 'sha1' や 'sha256' です。 password と salt はバイト列のバッファとして解釈されます。アプリケーションとライブラリは、 password を適切な長さ (例えば 1024) に制限すべきです。 salt は
os.urandom()のような適切なソースからの、およそ 16 バイトかそれ以上のバイト列にするべきです。iterations の回数は、ハッシュアルゴリズムと計算能力に基づいて選んでください。 2022 年時点では、SHA-256 で数十万回の反復が推奨されています。 アプリケーションに最適な値を選ぶ方法とその根拠については、NIST-SP-800-132 の 付録 A.2.2 を参照してください。 stackexchange pbkdf2 iterations question の回答にも詳しい説明があります。
dklen は、導出されたバイト列の鍵の長さです。 dklen が
Noneの場合、ハッシュアルゴリズム hash_name のダイジェストサイズが使われます。例えば SHA-512 では 64 です。>>> from hashlib import pbkdf2_hmac >>> our_app_iters = 500_000 # Application specific, read above. >>> dk = pbkdf2_hmac('sha256', b'password', b'bad salt' * 2, our_app_iters) >>> dk.hex() '15530bba69924174860db778f2c6f8104d3aaf9d26241840c8c4a641c8d000a9'
この関数は、Python が OpenSSL を使ってコンパイルされている場合にのみ利用できます。
Added in version 3.4.
バージョン 3.12 で変更: この関数は、Python が OpenSSL を使ってビルドされている場合にのみ利用できるようになりました。 低速な純 Python 実装は削除されました。
- hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64)¶
この関数は、 RFC 7914 で定義されるscrypt のパスワードに基づいた鍵導出関数を提供します。
password と salt は bytes-like object でなければなりません。アプリケーションとライブラリは、 password を適切な長さ (例えば 1024) に制限すべきです。 salt は
os.urandom()のような適切なソースからの、およそ 16 バイトかそれ以上のバイト列にするべきです。n は CPU とメモリのコスト係数、r はブロックサイズ、p は並列化係数です。 maxmem はメモリ使用量を制限します (OpenSSL 1.1.0 のデフォルトは 32 MiB)。 dklen は導出する鍵のバイト単位の長さです。
Added in version 3.6.
BLAKE2¶
BLAKE2 は RFC 7693 で定義された暗号学的ハッシュ関数で、次の 2 種類があります。
BLAKE2b は 64 ビットプラットフォーム向けに最適化されており、1〜64 バイトの任意の長さのダイジェストを生成します。
BLAKE2s は 8〜32 ビットプラットフォーム向けに最適化されており、1〜32 バイトの任意の長さのダイジェストを生成します。
BLAKE2 は 鍵付きモード (HMAC より高速で単純な代替手段)、ソルト付きハッシュ化、パーソナライズ、ツリーハッシング をサポートします。
このモジュールのハッシュオブジェクトは、標準ライブラリの hashlib オブジェクトの API に従います。
ハッシュオブジェクトの作成¶
新しいハッシュオブジェクトは、コンストラクタ関数を呼び出すことで生成されます:
- hashlib.blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True)¶
- hashlib.blake2s(data=b'', *, digest_size=32, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True)¶
これらの関数は、BLAKE2b または BLAKE2s を計算するための、対応するハッシュオブジェクトを返します。 次の一般的な引数を任意に指定できます。
data: 最初にハッシュ計算に使うデータのチャンクで、bytes-like object でなければなりません。 位置引数としてのみ渡せます。
digest_size: 出力するダイジェストのバイト数。
key: 鍵付きハッシュ化のための鍵 (BLAKE2b では最大 64 バイト、BLAKE2s では最大 32 バイト)。
salt: ランダム化ハッシュ化のためのソルト (BLAKE2b では最大 16 バイト、BLAKE2s では最大 8 バイト)。
person: パーソナライズ用の文字列 (BLAKE2b では最大 16 バイト、BLAKE2s では最大 8 バイト)。
下の表は一般的なパラメータの上限 (バイト単位) です:
Hash |
digest_size |
len(key) |
len(salt) |
len(person) |
|---|---|---|---|---|
BLAKE2b |
64 |
64 |
16 |
16 |
BLAKE2s |
32 |
32 |
8 |
8 |
注釈
BLAKE2 の仕様はソルトとパーソナライズ引数の長さを固定していますが、この実装では利便性のため、規定の長さまでの任意のサイズのバイト文字列を受け付けます。
引数の長さが規定より短ければゼロで埋めるため、例えば b'salt' と b'salt\x00' は同じ値になります。
(key はこのようには扱いません。)
これらのサイズは以下に述べるモジュール constants で利用できます。
コンストラクタ関数は以下のツリーハッシングパラメタを受け付けます:
fanout: ファンアウト (0〜255。 無制限なら 0、逐次モードでは 1)。
depth: ツリーの深さの最大値 (1〜255。 無制限なら 255、逐次モードでは 1)。
leaf_size: 葉の最大バイト長 (0〜
2**32-1。 無制限の場合や逐次モードでは 0)。node_offset: ノードのオフセット (BLAKE2b では 0〜
2**64-1、BLAKE2s では 0〜2**48-1。 最初の、つまり最も左の葉や、逐次モードでは 0)。node_depth: ノードの深さ (0〜255。 葉や逐次モードでは 0)。
inner_size: 内部ダイジェストのサイズ (BLAKE2b では 0〜64、BLAKE2s では 0〜32。 逐次モードでは 0)。
last_node: 処理中のノードが最後のノードかどうかを示すブール値 (逐次モードでは
False)。
ツリーハッシングの詳しい説明については、BLAKE2 の仕様 の 2.10 節を参照してください。
定数¶
- blake2b.SALT_SIZE¶
- blake2s.SALT_SIZE¶
ソルト長(コンストラクタが受け付けれる最大長)
- blake2b.PERSON_SIZE¶
- blake2s.PERSON_SIZE¶
パーソナライズ用の文字列の長さ (コンストラクタが受け付ける最大長)。
- blake2b.MAX_KEY_SIZE¶
- blake2s.MAX_KEY_SIZE¶
最大キー長
- blake2b.MAX_DIGEST_SIZE¶
- blake2s.MAX_DIGEST_SIZE¶
ハッシュ関数が出力しうるダイジェストの最大長
使用例¶
簡単なハッシュ化¶
データのハッシュを計算するには、まず適切なコンストラクタ関数 (blake2b() または blake2s()) でハッシュオブジェクトを作成します。
次にオブジェクトの update() を呼び出してデータで更新し、最後に digest() (16 進数の文字列を得る場合は hexdigest()) を呼び出してダイジェストを取得します。
>>> from hashlib import blake2b
>>> h = blake2b()
>>> h.update(b'Hello world')
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
手順を短くするために、最初のデータのチャンクをコンストラクタに位置引数として直接渡すこともできます。
>>> from hashlib import blake2b
>>> blake2b(b'Hello world').hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
hash.update() を必要な回数だけ呼び出して、ハッシュを順次更新できます。
>>> from hashlib import blake2b
>>> items = [b'Hello', b' ', b'world']
>>> h = blake2b()
>>> for item in items:
... h.update(item)
...
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
異なるダイジェストサイズの使用¶
BLAKE2 はダイジェストの長さを、BLAKE2bでは64バイトまで、BLAKE2sでは32バイトまでのダイジェスト長を指定できます。例えばSHA-1を、出力を同じ長さのままでBLAKE2bで置き換えるには、BLAKE2bに20バイトのダイジェストを生成するように指示できます:
>>> from hashlib import blake2b
>>> h = blake2b(digest_size=20)
>>> h.update(b'Replacing SHA1 with the more secure function')
>>> h.hexdigest()
'd24f26cf8de66472d58d4e1b1774b4c9158b1f4c'
>>> h.digest_size
20
>>> len(h.digest())
20
ダイジェストサイズが異なるハッシュオブジェクトは、まったく異なる出力を生成します (短いハッシュは長いハッシュの先頭部分では ありません)。 BLAKE2b と BLAKE2s は、出力の長さが同じでも異なる出力を生成します。
>>> from hashlib import blake2b, blake2s
>>> blake2b(digest_size=10).hexdigest()
'6fa1d8fcfd719046d762'
>>> blake2b(digest_size=11).hexdigest()
'eb6ec15daf9546254f0809'
>>> blake2s(digest_size=10).hexdigest()
'1bf21a98c78a1c376ae9'
>>> blake2s(digest_size=11).hexdigest()
'567004bf96e4a25773ebf4'
鍵付きハッシュ化¶
鍵付きハッシュ化は、ハッシュベースのメッセージ認証コード (HMAC) より高速で単純な代替手段として、認証に使えます。 BLAKE から受け継いだ強強強識別不可能性 (indifferentiability) により、BLAKE2 は prefix-MAC モードで安全に使えます。
この例では、鍵 b'pseudorandom key' を使って、メッセージ b'message data' の 128 ビット認証コードを 16 進数形式で取得します。
>>> from hashlib import blake2b
>>> h = blake2b(key=b'pseudorandom key', digest_size=16)
>>> h.update(b'message data')
>>> h.hexdigest()
'3d363ff7401e02026f4a4687d4863ced'
実用例として、ウェブアプリケーションがユーザーに送る Cookie に共通鍵で署名し、後で検証して改ざんされていないことを確認できます。
>>> from hashlib import blake2b
>>> from hmac import compare_digest
>>>
>>> SECRET_KEY = b'pseudorandomly generated server secret key'
>>> AUTH_SIZE = 16
>>>
>>> def sign(cookie):
... h = blake2b(digest_size=AUTH_SIZE, key=SECRET_KEY)
... h.update(cookie)
... return h.hexdigest().encode('utf-8')
>>>
>>> def verify(cookie, sig):
... good_sig = sign(cookie)
... return compare_digest(good_sig, sig)
>>>
>>> cookie = b'user-alice'
>>> sig = sign(cookie)
>>> print("{0},{1}".format(cookie.decode('utf-8'), sig))
user-alice,b'43b3c982cf697e0c5ab22172d1ca7421'
>>> verify(cookie, sig)
True
>>> verify(b'user-bob', sig)
False
>>> verify(cookie, b'0102030405060708090a0b0c0d0e0f00')
False
BLAKE2 には専用の鍵付きハッシュ化モードがありますが、もちろん hmac モジュールを使って HMAC を構成することもできます。
>>> import hmac, hashlib
>>> m = hmac.new(b'secret key', digestmod=hashlib.blake2s)
>>> m.update(b'message')
>>> m.hexdigest()
'e3c8102868d28b5ff85fc35dda07329970d1a01e273c37481326fe0c861c8142'
ランダム化ハッシュ化¶
salt 引数を設定すると、ハッシュ関数にランダム性を導入できます。 ランダム化ハッシュ化は、デジタル署名で使うハッシュ関数への衝突攻撃を防ぐのに役立ちます。
ランダム化ハッシュ化は、メッセージ作成者がメッセージの全体または一部を作成し、別の当事者である署名者が署名する状況を想定して設計されています。 作成者が暗号学的ハッシュ関数の衝突 (同じハッシュ値を生成する 2 つのメッセージ) を見つけられる場合、同じハッシュ値とデジタル署名を生成しながら異なる結果をもたらす、意味の通る複数のメッセージを用意できるかもしれません (例えば、口座への送金額を 10 ドルではなく 100 万ドルにするなど)。 暗号学的ハッシュ関数は衝突耐性を主要な目標として設計されていますが、暗号学的ハッシュ関数への攻撃が現在集中的に研究されているため、特定の関数の衝突耐性が期待を下回る可能性があります。 ランダム化ハッシュ化は、ハッシュ関数の衝突を現実的に見つけられる場合でも、デジタル署名の生成過程で最終的に同じハッシュ値になるメッセージを作成者が複数作れる可能性を減らし、署名者をさらに保護します。 ただし、メッセージのすべてを署名者自身が作成する場合には、ランダム化ハッシュ化の使用によりデジタル署名の安全性が下がることがあります。
BLAKE2 では、ソルトを圧縮関数の毎回の入力としてではなく、初期化時にハッシュ関数への一度だけの入力として処理します。
警告
BLAKE2 や SHA-256 などの汎用の暗号学的ハッシュ関数による ソルト付きハッシュ化 (あるいは単なるハッシュ化) は、パスワードのハッシュ化には適していません。 詳しくは BLAKE2 FAQ を参照してください。
>>> import os
>>> from hashlib import blake2b
>>> msg = b'some message'
>>> # Calculate the first hash with a random salt.
>>> salt1 = os.urandom(blake2b.SALT_SIZE)
>>> h1 = blake2b(salt=salt1)
>>> h1.update(msg)
>>> # Calculate the second hash with a different random salt.
>>> salt2 = os.urandom(blake2b.SALT_SIZE)
>>> h2 = blake2b(salt=salt2)
>>> h2.update(msg)
>>> # The digests are different.
>>> h1.digest() != h2.digest()
True
パーソナライズ¶
同じ入力でも用途ごとに異なるダイジェストを生成するようにハッシュ関数を設定すると、役立つ場合があります。 Skein ハッシュ関数の作者は次のように述べています。
すべてのアプリケーション設計者に、この方法を真剣に検討することを勧めます。 私たちは、プロトコルのある部分で計算したハッシュを、まったく別の部分で使えてしまうプロトコルを数多く見てきました。 これは、2 つのハッシュ計算が似たデータや関連したデータに対して行われ、攻撃者がアプリケーションに同じデータを入力させられるためです。 プロトコルで使う各ハッシュ関数をパーソナライズすれば、この種の攻撃を完全に防げます。
(The Skein Hash Function Family、21 ページ)
BLAKE2は person 引数にバイト列を渡すことでパーソナライズできます:
>>> from hashlib import blake2b
>>> FILES_HASH_PERSON = b'MyApp Files Hash'
>>> BLOCK_HASH_PERSON = b'MyApp Block Hash'
>>> h = blake2b(digest_size=32, person=FILES_HASH_PERSON)
>>> h.update(b'the same content')
>>> h.hexdigest()
'20d9cd024d4fb086aae819a1432dd2466de12947831b75c5a30cf2676095d3b4'
>>> h = blake2b(digest_size=32, person=BLOCK_HASH_PERSON)
>>> h.update(b'the same content')
>>> h.hexdigest()
'cf68fb5761b9c44e7878bfb2c4c9aea52264a80b75005e65619778de59f383a3'
パーソナライズと鍵付きモードを組み合わせることで、1 つの鍵から異なる鍵を導出することもできます。
>>> from hashlib import blake2s
>>> from base64 import b64decode, b64encode
>>> orig_key = b64decode(b'Rm5EPJai72qcK3RGBpW3vPNfZy5OZothY+kHY6h21KM=')
>>> enc_key = blake2s(key=orig_key, person=b'kEncrypt').digest()
>>> mac_key = blake2s(key=orig_key, person=b'kMAC').digest()
>>> print(b64encode(enc_key).decode('utf-8'))
rbPb15S/Z9t+agffno5wuhB77VbRi6F9Iv2qIxU7WHw=
>>> print(b64encode(mac_key).decode('utf-8'))
G9GtHFE1YluXY1zWPlYk1e/nWfu0WSEb0KRcjhDeP/o=
ツリーモード¶
これが二つの葉ノードからなる最小の木をハッシュする例です:
10
/ \
00 01
この例では 64 バイトの内部ダイジェストを使い、32 バイトの最終ダイジェストを返します。
>>> from hashlib import blake2b
>>>
>>> FANOUT = 2
>>> DEPTH = 2
>>> LEAF_SIZE = 4096
>>> INNER_SIZE = 64
>>>
>>> buf = bytearray(6000)
>>>
>>> # 左の葉
... h00 = blake2b(buf[0:LEAF_SIZE], fanout=FANOUT, depth=DEPTH,
... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
... node_offset=0, node_depth=0, last_node=False)
>>> # 右の葉
... h01 = blake2b(buf[LEAF_SIZE:], fanout=FANOUT, depth=DEPTH,
... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
... node_offset=1, node_depth=0, last_node=True)
>>> # 根ノード
... h10 = blake2b(digest_size=32, fanout=FANOUT, depth=DEPTH,
... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
... node_offset=0, node_depth=1, last_node=True)
>>> h10.update(h00.digest())
>>> h10.update(h01.digest())
>>> h10.hexdigest()
'3ad2a9b37c6070e374c7a8c508fe20ca86b6ed54e286e93a0318e95e881db5aa'
クレジット:¶
BLAKE2 は*Jean-Philippe Aumasson*、 Luca Henzen、 Willi Meier そして Raphael C.-W. Phan によって作成された SHA-3 の最終候補である BLAKE を元に、Jean-Philippe Aumasson、 Samuel Neves、 Zooko Wilcox-O'Hearn, そして Christian Winnerlein によって設計されました。
それは、 Daniel J. Bernstein によって設計されたChaCha 暗号由来のアルゴリズムを用いています。
標準ライブラリは pyblake2 モジュールを基礎として実装されています。 このモジュールは Dmitry Chestnykh によって、Samuel Neves が作成した C実装を元に書かれました。 このドキュメントは、pyblake2 からコピーされ、Dmitry Chestnykh によって書かれました。
Christian Heimes によって、一部のCコードがPython向けに書き直されました。
以下の public domain dedicationが、Cのハッシュ関数実装と、拡張コードと、このドキュメントに適用されます:
法律上可能な範囲で、著作者は、このソフトウェアに関するすべての著作権および関連する権利・著作隣接権を、世界中でパブリックドメインに提供しています。 このソフトウェアは、いかなる保証もなく配布されています。
このソフトウェアには CC0 Public Domain Dedication のコピーが同梱されているはずです。 ない場合は https://creativecommons.org/publicdomain/zero/1.0/ を参照してください。
以下の人々は開発を支援し、または Creative Commons Public Domain Dedication 1.0 Universal に従って、変更内容をプロジェクトおよびパブリックドメインに提供しました。
Alexandr Sokolovskiy
参考
hmacモジュールハッシュを用いてメッセージ認証コードを生成するモジュールです。
base64モジュールバイナリハッシュを非バイナリ環境用にエンコードするもうひとつの方法です。
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.180-4.pdf
セキュアハッシュアルゴリズムに関する FIPS 180-4 の刊行物。
- https://csrc.nist.gov/pubs/fips/202/final
SHA-3 標準に関する FIPS 202 の刊行物。
- https://www.blake2.net/
BLAKE2 の公式ウェブサイト
- https://en.wikipedia.org/wiki/Cryptographic_hash_function
どのアルゴリズムにどんな既知の問題があって、それが実際に利用する際にどう影響するかについての Wikipedia の記事。
- https://www.ietf.org/rfc/rfc8018.txt
PKCS #5: パスワードに基づく暗号仕様 バージョン 2.1
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf
パスワードに基づく鍵導出についての NIST の推奨事項。