質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

解決済

Python3.6でのdictのキー順維持と、hash randomizeによるDoS回避の関係について

shimizukawa
shimizukawa

総合スコア1845

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1回答

10リアクション

13クリップ

5246閲覧

投稿2017/03/16 03:15

編集2017/03/20 01:59

訂正 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つに分けます。

  1. **(B)**で、DDoS回避のためにdictキー順をランダム化したかった訳ではなく、object.__hash__がランダム化された副作用でdictキー順が起動毎にランダムになった、という理解であってますか?

  2. Python3.6未満でも、PYTHONHASHSEED環境変数を指定すれば、起動毎には変化しない以前の挙動を復活させる方法がありますが、これをやるとDDoS回避の実装を無効化することになるという理解であってますか?

  3. **(C)**で、dictのキー順が維持されるようになりましたが、これはキー順がobject.__hash__の結果に依存しなくなった、という理解で合っていますか? DSAS開発者の部屋:Python に現在実装中の Compact dict の紹介 からそのように読み解きました。

sharow, Eggpan, 5o5o_wagon, terapyon, can110, tell_k, ikuwow, driller, yohhoy, jun68ykt👍を押しています

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

jun68ykt

2018/09/16 08:35

詳細に突っ込んだご質問ありがとうございます。以下の質問 https://teratail.com/questions/146865 への回答の追記1にてこちらの質問を参照させて頂きました。
shimizukawa

2018/09/18 23:26

はい。ありがとうございます

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。