web-dev-qa-db-ja.com

Python 3.3のハッシュ関数はセッション間で異なる結果を返します

BloomFilterをpython 3.3で実装し、セッションごとに異なる結果が得られました。この奇妙な動作をドリルダウンすると、内部のhash()関数に到達しました。同じ文字列に対して異なるハッシュ値を返しますすべてのセッション。

例:

>>> hash("235")
-310569535015251310

-----新しいpythonコンソールを開く-----

>>> hash("235")
-1900164331622581997

なぜこうなった?なぜこれが便利ですか?

51
redlus

Pythonは、ランダムハッシュシードを使用して、衝突するように設計されたキーを送信することにより、攻撃者がアプリケーションをtarピットするのを防ぎます。 元の脆弱性の開示 を参照してください。ハッシュをランダムシード(起動時に1回設定)で相殺することにより、攻撃者はどのキーが衝突するかを予測できなくなります。

PYTHONHASHSEED環境変数 ;を設定することにより、固定シードを設定したり、機能を無効にしたりできます。デフォルトはrandomですが、機能を完全に無効にする_0_を使用して、固定の正の整数値に設定できます。

Pythonバージョン2.7および3.2では、デフォルトで機能が無効になっています(_-R_スイッチを使用するか、_PYTHONHASHSEED=random_を設定して有効にします)。 Python 3.3以降ではデフォルトで有効になっています。

Python辞書またはセットのキーの順序に依存している場合は、しないでください。Pythonは、ハッシュテーブルを使用してこれらのタイプとorder 挿入および削除履歴に依存 およびランダムハッシュシード。

object.__hash__()特殊メソッドのドキュメント も参照してください:

:デフォルトでは、str、byte、およびdatetimeオブジェクトの__hash__()値は、予測不可能なランダム値で「ソルト」されます。それらは個々のPythonプロセス内で一定のままですが、Pythonを繰り返し呼び出しても予測できません。
これは、辞書挿入の最悪の場合のパフォーマンスO(n ^ 2)の複雑さを悪用する慎重に選択された入力によって引き起こされるサービス拒否に対する保護を提供することを目的としています。詳細については、 http://www.ocert.org/advisories/ocert-2011-003.html を参照してください。
ハッシュ値の変更は、dict、set、およびその他のマッピングの反復順序に影響します。 Pythonはこの順序について保証していません(通常、32ビットと64ビットのビルド間で異なります)。
PYTHONHASHSEEDも参照してください。

安定したハッシュの実装が必要な場合は、おそらく hashlib module ;をご覧ください。これは暗号化ハッシュ関数を実装します。 pybloomプロジェクトはこのアプローチを使用します

オフセットはプレフィックスとサフィックス(それぞれ開始値と最終XORされた値)で構成されているため、残念ながらオフセットを保存することはできません。プラス面では、これは攻撃者がタイミング攻撃でもオフセットを簡単に決定できないことを意味します。

77
Martijn Pieters

ハッシュのランダム化は Python でデフォルトで有効になっています。これはセキュリティ機能です:

ハッシュランダム化は、dict構造の最悪の場合のパフォーマンスを活用する入念に選択された入力によって引き起こされるサービス拒否に対する保護を提供することを目的としています。

2.6.8からの以前のバージョンでは、コマンドラインで-Rまたは [〜#〜] pythonhashseed [〜#〜] 環境オプションを使用してスイッチをオンにすることができました。

PYTHONHASHSEEDをゼロに設定することで、スイッチをオフにできます。

5
Peter Wood