ハッシュと暗号は違うぞ! PHPカンファレンス関西2017 / Hash or Encryption

ハッシュと暗号は違うぞ! PHPカンファレンス関西2017 / Hash or Encryption

PHPカンファレンス関西 2017の発表資料です

40575ebf9c2f4a6e3bcb68630f446a3b?s=128

HASEGAWA Tomoki

July 15, 2017
Tweet

Transcript

  1. 3.

    ライフワーク: Web / iOSアプリ開発, ビール, 電子工作,
 サッカー観戦, レンタルカートレース, … 長谷川

    智希 Web / iOS App Development, Beer, IoT, Watch soccer match, Rental Kart Racing, … デジタルサーカス株式会社 副団長CTO Digital Circus, Inc. Vice-master CTO Tokyo, Japan Lifeworks: @tomzoh
  2. 4.
  3. 5.
  4. 14.
  5. 15.
  6. 25.

    ハッシュ関数 • 関数: sin(θ), cos(θ), f(x) md5, sha-1, sha-512 •

    データをハッシュ関数に入力するとハッシュ値 が出力される。 • ハッシュ関数の例: • ハッシュ関数
  7. 71.

    UbuntuのISO配布サイト c94d54942a2954cf852884d656224186 *ubuntu-16.04-desktop-amd64.iso 610c4a399df39a78866f9236b8c658da *ubuntu-16.04-desktop-i386.iso 23e97cd5d4145d4105fbf29878534049 *ubuntu-16.04-server-amd64.img 23e97cd5d4145d4105fbf29878534049 *ubuntu-16.04-server-amd64.iso 494c03028524dff2de5c41a800674692

    *ubuntu-16.04-server-i386.img 494c03028524dff2de5c41a800674692 *ubuntu-16.04-server-i386.iso 17643c29e3c4609818f26becf76d29a3 *ubuntu-16.04.1-desktop-amd64.iso 9e4e30c37c99b4e029b4bfc2ee93eec2 *ubuntu-16.04.1-desktop-i386.iso d2d939ca0e65816790375f6826e4032f *ubuntu-16.04.1-server-amd64.img d2d939ca0e65816790375f6826e4032f *ubuntu-16.04.1-server-amd64.iso 455206c599c25d6a576ba23ca906741a *ubuntu-16.04.1-server-i386.img 455206c599c25d6a576ba23ca906741a *ubuntu-16.04.1-server-i386.iso
  8. 73.

    推測しにくいURLの生成 「/user/1とか、IDがURLに丸見えなの、カッコ
 悪いな…」  id username hash … 1 bob

    4818…920a … 2 jones 4c46…3902 … : : : … https://example.com/user/4c46bc790ffe655a1e65acfacf95da50cd4d3902
  9. 76.

     id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login
  10. 77.

     id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login
  11. 78.

     id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login
  12. 79.

     id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login 入力されたパスワードと DBのパスワードを比較
  13. 80.

     id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login 入力されたパスワードと DBのパスワードを比較 入力されたパスワードとDBのパス ワードが一致 → ログイン成功
  14. 84.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : … 「パスワードそのものじゃなくて、
 パスワードのハッシュ値を保存しておこう!」 パスワードのハッシュ値
  15. 87.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Signup 3c65…1d8b sha1 DBにはハッシュ化されたパスワードを保存
  16. 88.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login
  17. 89.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login
  18. 90.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login
  19. 91.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login 入力されたパスワードを ハッシュ化 3c65…1d8b sha1
  20. 92.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login 3c65…1d8b sha1 入力されたパスワードを ハッシュ化したものと DBに保存されたものを比較
  21. 93.

     id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login 入力されたパスワードをハッシュ化したものと DBに保存されたハッシュ化したパスワードが一致 → ログイン成功 3c65…1d8b sha1 入力されたパスワードを ハッシュ化したものと DBに保存されたものを比較
  22. 101.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer
  23. 102.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  24. 103.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 4,294,967,296通り 任意長のデータから2bitの ハッシュ値を出力する
  25. 104.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 4通り sha-beer 4,294,967,296通り 任意長のデータから2bitの ハッシュ値を出力する
  26. 105.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  27. 106.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  28. 107.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  29. 108.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  30. 109.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  31. 110.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  32. 111.

    元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 衝突! 任意長のデータから2bitの ハッシュ値を出力する
  33. 140.

    推測しにくいURLの生成 「/user/1とか、IDがURLに丸見えなの、カッコ
 悪いな…」  id username hash … 1 bob

    4818…920a … 2 jones 4c46…3902 … : : : … https://example.com/user/4c46bc790ffe655a1e65acfacf95da50cd4d3902
  34. 144.
  35. 149.

    原像推測による攻撃の対策 • 元データがバレない様にする。 • 元データに長い文字列(ソルト)を追加する。 $salt = "aemi4ahcoh7weeN2euth"; $url =

    sprintf("/user/%s", md5($salt.$userId)); • 攻撃者は「aemi4ahcoh7weeN2euth1」を推測しなければならなくなる。 • 「連番とかをわかりにくくする」様な用途では、ソルトを付けない形で ハッシュ関数を使うことは無いと思って良い。 • 元データが「1」とかだからバレる。
  36. 151.

    ログインパスワードの保存  id username hashed_password … 1 bob 3c65…1d8b …

    2 jones d578…fa1f … : : : … 「パスワードそのものじゃなくて、
 パスワードのハッシュ値を保存しておこう!」 パスワードのハッシュ値
  37. 165.

    ハッシュと暗号 ハッシュ関数によるハッシュ化 一方向 / ハッシュ値から元データに戻せないことが前提 md5, sha-1, sha-512, … 暗号化

    / 復号 双方向 / 暗号文から平文に戻せることが前提 秘密裏に通信をすることを目的とする AES, DES, RSA n
  38. 170.

    ハッシュと暗号と心強さと 難読化 一方向 / プログラムなどを読みにくくするための変換。 結果としてファイルサイズが小さくなるので「圧縮」って呼 んだりも。 JavaScriptやJavaでよく利用される。 n 双方向

    / エンコードされたものをデコードできることが前提。 鍵の要素が無いため、アルゴリズムを知っていれば誰でも元に 戻せる。 urlencode(), Base64, … エンコード / デコード
  39. 172.
  40. 173.

    まとめ • ハッシュ関数はデータをハッシュ値に一方向に
 変換するもの。 • ハッシュ関数を使う時は必ず… • 入力データにソルトを追加する • 衝突の可能性を考慮に入れる

    • 暗号化、エンコード、難読化とは違う。 • ハッシュや暗号を使う時は、なぜそれを使うか、
 なぜその判断をすべきかを考えよう。
  41. 190.

    $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  42. 191.

    $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  43. 192.

    $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  44. 193.

    $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  45. 194.

    $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji 0x1200
  46. 195.

    $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200
  47. 196.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200
  48. 197.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200
  49. 198.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 sha-beer
  50. 199.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  51. 200.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  52. 201.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  53. 202.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  54. 203.

    echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  55. 204.
  56. 207.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200
  57. 208.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200
  58. 209.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200 okazaki:shinji
  59. 210.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200 okazaki:shinji
  60. 211.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200 okazaki:shinji
  61. 212.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto sha-beer 0x1200 okazaki:shinji
  62. 213.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto sha-beer 0x1200 okazaki:shinji
  63. 214.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto sha-beer 0x1200 okazaki:shinji
  64. 215.

    $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto sha-beer 0x1200 okazaki:shinji 衝突!
  65. 220.

    hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’,
  66. 221.

    hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’,
  67. 222.

    hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’, 外部から任意に作成可能
  68. 223.

    hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’, 外部から任意に作成可能 すべてのキーを 衝突させると? ?
  69. 224.

    hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’, 外部から任意に作成可能 すべてのキーを 衝突させると? ? 著しくパフォー マンスが低下する
  70. 231.
  71. 232.
  72. 233.
  73. 235.

    <?php $salt = 'iAakR1rFT2CzRWvV'; $plain = '09012345678'; $hashed = sha1($salt.$plain);

    foreach ([5, 7, 9] as $second){ for ($i = 0; $i <= 99999999; $i++){ $check = sprintf("0%d0%08d", $second, $i); if (sha1($salt.$check) == $hashed){ printf("Got it! Plain text is %s".PHP_EOL, $check); return; } } }
  74. 241.
  75. 245.
  76. 246.
  77. 247.
  78. 264.

    妥当なソルト • ソルトとして妥当な文字列は何か • 長さが一定以上あることだけど… • 長いソルトはハッシュ関数に入力するデータの情報量を増や す。 • 情報量が増えると衝突を起こしやすくなるかもしれない。

    • 一般的に使用されるハッシュ関数はこの様な「近いデータ (ソルトが同じで元データ部分だけが違うデータ)」が衝突 しにくい様に設計されている。 • 20文字程度、とか、26文字程度、とかいろいろ言われてい る。
  79. 265.

    encrypt / decrypt • 暗号化と復号 • 暗号化 encrypt • 復号

    decrypt • 日本語では「暗号」は名詞「復号」は動詞。 • なので「暗号化」として動詞化する。 • 英語は「encrypt」も「decrypt」も動詞。 • シンプルでうらやましいね!
  80. 269.
  81. 271.

    PHPerKaigi 2018 https://phperkaigi.jp スポンサー募集…するかも 2018.03.10(土) • PHPerのためのカンファレンス • 東京都練馬区 Coconeriホールにて

    • 朝から晩までテックトーク • 夕方からはビールを飲みながら • 夜はクラフトビールで懇親会