Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

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

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

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

HASEGAWA Tomoki

July 15, 2017
Tweet

More Decks by HASEGAWA Tomoki

Other Decks in Technology

Transcript

  1. ライフワーク: 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. ハッシュ関数 • 関数: sin(θ), cos(θ), f(x) md5, sha-1, sha-512 •

    データをハッシュ関数に入力するとハッシュ値 が出力される。 • ハッシュ関数の例: • ハッシュ関数
  3. 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
  4. 推測しにくいURLの生成 「/user/1とか、IDがURLに丸見えなの、カッコ
 悪いな…」  id username hash … 1 bob

    4818…920a … 2 jones 4c46…3902 … : : : … https://example.com/user/4c46bc790ffe655a1e65acfacf95da50cd4d3902
  5.  id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login
  6.  id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login
  7.  id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login
  8.  id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login 入力されたパスワードと DBのパスワードを比較
  9.  id username password … 1 bob M2teM2P0 … 2

    jones tqigg75Y … : : : …  username password bob ••• Login 入力されたパスワードと DBのパスワードを比較 入力されたパスワードとDBのパス ワードが一致 → ログイン成功
  10.  id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : … 「パスワードそのものじゃなくて、
 パスワードのハッシュ値を保存しておこう!」 パスワードのハッシュ値
  11.  id username hashed_password … 1 bob 3c65…1d8b … 2

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

    jones d578…fa1f … : : : …  username password bob ••• Login
  13.  id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login
  14.  id username hashed_password … 1 bob 3c65…1d8b … 2

    jones d578…fa1f … : : : …  username password bob ••• Login
  15.  id username hashed_password … 1 bob 3c65…1d8b … 2

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

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

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

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer
  19. 元データ 32bit data 1 data 2 data 3 data 4

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 任意長のデータから2bitの ハッシュ値を出力する
  20. 元データ 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の ハッシュ値を出力する
  21. 元データ 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の ハッシュ値を出力する
  22. 元データ 32bit data 1 data 2 data 3 data 4

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

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

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

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

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

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

    data 5 ハッシュ値 2bit hash 1 hash 2 hash 3 hash 4 sha-beer 衝突! 任意長のデータから2bitの ハッシュ値を出力する
  29. 推測しにくいURLの生成 「/user/1とか、IDがURLに丸見えなの、カッコ
 悪いな…」  id username hash … 1 bob

    4818…920a … 2 jones 4c46…3902 … : : : … https://example.com/user/4c46bc790ffe655a1e65acfacf95da50cd4d3902
  30. 原像推測による攻撃の対策 • 元データがバレない様にする。 • 元データに長い文字列(ソルト)を追加する。 $salt = "aemi4ahcoh7weeN2euth"; $url =

    sprintf("/user/%s", md5($salt.$userId)); • 攻撃者は「aemi4ahcoh7weeN2euth1」を推測しなければならなくなる。 • 「連番とかをわかりにくくする」様な用途では、ソルトを付けない形で ハッシュ関数を使うことは無いと思って良い。 • 元データが「1」とかだからバレる。
  31. ログインパスワードの保存  id username hashed_password … 1 bob 3c65…1d8b …

    2 jones d578…fa1f … : : : … 「パスワードそのものじゃなくて、
 パスワードのハッシュ値を保存しておこう!」 パスワードのハッシュ値
  32. ハッシュと暗号 ハッシュ関数によるハッシュ化 一方向 / ハッシュ値から元データに戻せないことが前提 md5, sha-1, sha-512, … 暗号化

    / 復号 双方向 / 暗号文から平文に戻せることが前提 秘密裏に通信をすることを目的とする AES, DES, RSA n
  33. ハッシュと暗号と心強さと 難読化 一方向 / プログラムなどを読みにくくするための変換。 結果としてファイルサイズが小さくなるので「圧縮」って呼 んだりも。 JavaScriptやJavaでよく利用される。 n 双方向

    / エンコードされたものをデコードできることが前提。 鍵の要素が無いため、アルゴリズムを知っていれば誰でも元に 戻せる。 urlencode(), Base64, … エンコード / デコード
  34. まとめ • ハッシュ関数はデータをハッシュ値に一方向に
 変換するもの。 • ハッシュ関数を使う時は必ず… • 入力データにソルトを追加する • 衝突の可能性を考慮に入れる

    • 暗号化、エンコード、難読化とは違う。 • ハッシュや暗号を使う時は、なぜそれを使うか、
 なぜその判断をすべきかを考えよう。
  35. $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  36. $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  37. $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  38. $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji
  39. $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ 0x02 アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto sha-beer kagawa:shinji 0x1200
  40. $array[‘kagawa’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200
  41. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200
  42. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200
  43. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 sha-beer
  44. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  45. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  46. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  47. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  48. echo $array[‘kagawa’]; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02 0x03

    0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 0x1300 nagatomo:yuto kagawa:shinji 0x1200 0x02 sha-beer
  49. $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200
  50. $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200
  51. $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200 okazaki:shinji
  52. $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200 okazaki:shinji
  53. $array[‘okazaki’] = ‘shinji’; インデックス アドレス 0x00 0x1100 0x01 0x1000 0x02

    0x03 0x1300 連想配列とハッシュ アドレス データ 0x1000 honda:keisuke 0x1100 0x1200 kagawa:shinji 0x1300 nagatomo:yuto 0x1200 okazaki:shinji
  54. $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
  55. $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
  56. $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
  57. $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 衝突!
  58. hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’,
  59. hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’,
  60. hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’, 外部から任意に作成可能
  61. hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’, 外部から任意に作成可能 すべてのキーを 衝突させると? ?
  62. hashes $_POST = [ ‘okazaki’ ‘kiyotake’ ‘kagawa’ ‘honda’ : ‘eiji’

    ]; => ‘shinji’, => ‘hiroshi’, => ‘shinji’, => ‘keisuke’, => ‘kawashima’, 外部から任意に作成可能 すべてのキーを 衝突させると? ? 著しくパフォー マンスが低下する
  63. <?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; } } }
  64. 妥当なソルト • ソルトとして妥当な文字列は何か • 長さが一定以上あることだけど… • 長いソルトはハッシュ関数に入力するデータの情報量を増や す。 • 情報量が増えると衝突を起こしやすくなるかもしれない。

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

    decrypt • 日本語では「暗号」は名詞「復号」は動詞。 • なので「暗号化」として動詞化する。 • 英語は「encrypt」も「decrypt」も動詞。 • シンプルでうらやましいね!
  66. PHPerKaigi 2018 https://phperkaigi.jp スポンサー募集…するかも 2018.03.10(土) • PHPerのためのカンファレンス • 東京都練馬区 Coconeriホールにて

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