1. ホーム
  2. python

[解決済み] Python 3.3のハッシュ関数は、セッション間で異なる結果を返す

2022-05-24 11:51:40

質問

python 3.3でBloomFilterを実装したところ、セッションごとに異なる結果を得ました。この奇妙な動作を掘り下げていくと、内部の hash() 関数にたどり着きました。

例です。

>>> hash("235")
-310569535015251310

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

>>> hash("235")
-1900164331622581997

なぜこのようなことが起こるのでしょうか? なぜこれが便利なのか?

どのように解決するのですか?

Python はランダムなハッシュシードを使用して、攻撃者が衝突するように設計されたキーを送ることによって、アプリケーションを tar-pit することを防止します。以下を参照してください。 オリジナルの脆弱性の開示 . ランダムな種 (起動時に一度だけ設定される) でハッシュをオフセットすることにより、攻撃者はもはやどのキーが衝突するかを予測することができなくなります。

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

Python バージョン 2.7 と 3.2 では、この機能はデフォルトで無効になっています ( -R スイッチを使うか PYTHONHASHSEED=random を設定してください); Python 3.3 以降ではデフォルトで有効になっています。

もしあなたがPythonの集合におけるキーの順序に頼っていたのなら、そうではありません。Python はこれらの型とその順序を実装するためにハッシュテーブルを使用します。 は挿入と削除の履歴に依存します。 とランダムなハッシュシードに依存します。Python 3.5とそれ以前では、これは辞書にも適用されることに注意してください。

また object.__hash__() 特別なメソッドのドキュメント :

ノート : デフォルトでは __hash__() の値は、予測できないランダムな値で "塩付け" されます。これらは個々のPythonプロセス内では一定ですが、Pythonの繰り返し起動の間では予測不可能です。

これは、dict挿入の最悪の場合、O(n^2)の複雑さを利用する、慎重に選ばれた入力によって引き起こされるサービス拒否からの保護を提供することを意図しています。参照 http://www.ocert.org/advisories/ocert-2011-003.html を参照してください。

ハッシュ値を変更すると、ディクショ ン、セット、その他のマッピングの反復順序に影響します。Pythonはこの順序について決して保証していません(そしてそれは一般的に32ビットと64ビットビルドの間で変化します)。

また PYTHONHASHSEED .

安定したハッシュの実装が必要な場合は、おそらく hashlib モジュール これは暗号ハッシュ関数を実装しています。このモジュールは pybloomプロジェクトはこのアプローチを使っています。 .

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