"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.hexdigest()

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

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 の範囲全てを含み得る
   バイトの列です。

shake.hexdigest(length)

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

使用例:

>>> 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 万ドルにするなど)。 暗号学的ハッシュ関数は衝突耐性を主要な目
   標として設計されていますが、暗号学的ハッシュ関数への攻撃が現在集中
   的に研究されているため、特定の関数の衝突耐性が期待を下回る可能性が
   あります。 ランダム化ハッシュ化は、ハッシュ関数の衝突を現実的に見つ
   けられる場合でも、デジタル署名の生成過程で最終的に同じハッシュ値に
   なるメッセージを作成者が複数作れる可能性を減らし、署名者をさらに保
   護します。 ただし、メッセージのすべてを署名者自身が作成する場合には
   、ランダム化ハッシュ化の使用によりデジタル署名の安全性が下がること
   があります。

   (NIST SP-800-106「デジタル署名のためのランダム化ハッシュ化」)

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/nistspecialpublication8
  00-132.pdf
     パスワードに基づく鍵導出についての NIST の推奨事項。
