訂正 DDoS
ではなく、 DoS
でした。ベストアンサーを決定済みなので本文はそのままにしてタイトルだけ修正します。以降すべてDDoS -> DoS で読み替えお願いします。
###前提
Pythonは以前からdictのキーの順番は不定、とされてきました。
しかし、見た目上は何らかの固定の順番でdictのキーを取り出せていました。(不定だけど一定) --(A)
Python3.3では、 hash randomizeが導入されました。
導入された目的は、object.__hash__
のドキュメントに書いてあったので以下に引用します。
この目的は、慎重に選ばれた入力で辞書挿入の最悪性能 O(n^2) 計算量を悪用することで引き起こされるサービス妨害 (denial-of-service, DoS) に対する保護です。 詳細は http://www.ocert.org/advisories/ocert-2011-003.html を参照してください。
この導入によって、dictのキーの順番がインタプリタ起動毎に不定になりました。 --(B)
そしてPython3.6でdictの実装が変わり、dictが省メモリになり、キーの順番が維持されるようになりました。 ref: Python 3.6 の(個人的に)注目の変更点 - methaneのブログ --(C)
検証したこと
Python2.7.13で文字列のhash値を取得(**(B)**の確認)
$ python2.7 -c "print(hex(hash('abc')))" 0x142a6050a093d0a3 $ python2.7 -c "print(hex(hash('abc')))" 0x142a6050a093d0a3 $ python2.7 -c "print(hex(hash('abc')))" 0x142a6050a093d0a3
Python3.5.2で文字列のhash値を取得(**(B)**の確認)
$ python3.5 -c "print(hex(hash('abc')))" 0x53a97f418e279642 $ python3.5 -c "print(hex(hash('abc')))" -0x745a06d34cd5d4ed $ python3.5 -c "print(hex(hash('abc')))" 0x29736bbb038652f5
Python3.6.0で文字列のhash値を取得(**(B)**の確認)
$ python3.6 -c "print(hex(hash('abc')))" 0x11108253ed4a023b $ python3.6 -c "print(hex(hash('abc')))" -0x5dc778080cb917cd $ python3.6 -c "print(hex(hash('abc')))" -0x687164debf8ee240
Python2.7.13で辞書のキー順を取得(**(A)**の確認)
$ python2.7 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['a', 'c', 'b', 'e', 'd', 'g', 'f'] $ python2.7 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['a', 'c', 'b', 'e', 'd', 'g', 'f'] $ python2.7 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['a', 'c', 'b', 'e', 'd', 'g', 'f']
Python3.5.2で辞書のキー順を取得(**(B)**の確認)
$ python3.5 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['e', 'd', 'f', 'a', 'b', 'c', 'g'] $ python3.5 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['e', 'f', 'g', 'b', 'a', 'c', 'd'] $ python3.5 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['d', 'e', 'a', 'g', 'b', 'f', 'c']
Python3.6.0で辞書のキー順を取得(**(C)**の確認)
$ python3.6 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['a', 'b', 'c', 'd', 'e', 'f', 'g'] $ python3.6 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['a', 'b', 'c', 'd', 'e', 'f', 'g'] $ python3.6 -c "print(list(dict.fromkeys(list('abcdefg'))))" ['a', 'b', 'c', 'd', 'e', 'f', 'g']
質問
Python3.6では、セキュリティ上安全で、これまでOrderedDictを使っていたプログラムをdictで一部置き換え可能と考えてよいでしょうか?
複数の要素が絡み合っていそうなので、質問を以下の3つに分けます。
-
**(B)**で、DDoS回避のためにdictキー順をランダム化したかった訳ではなく、
object.__hash__
がランダム化された副作用でdictキー順が起動毎にランダムになった、という理解であってますか? -
Python3.6未満でも、PYTHONHASHSEED環境変数を指定すれば、起動毎には変化しない以前の挙動を復活させる方法がありますが、これをやるとDDoS回避の実装を無効化することになるという理解であってますか?
-
**(C)**で、dictのキー順が維持されるようになりましたが、これはキー順が
object.__hash__
の結果に依存しなくなった、という理解で合っていますか? DSAS開発者の部屋:Python に現在実装中の Compact dict の紹介 からそのように読み解きました。
回答1件
あなたの回答
tips
プレビュー