MW211 EXIT

devlog
PHP/パスワード管理(2)
2014年10月19日
パスワードを暗号化するのにハッシュ関数を使う。
以下は「md5()」を使った例。
┌──────────────────────────────────────┐
│$平文 = 'パスワード';                                                       │
│$暗号文 = md5($平文);                                                       │
├──────────────────────────────────────┤
│$入力文 = 'パスワード';                                                     │
│if (md5($入力文) == $暗号文) {                                              │
│    echo '合格';                                                            │
│} else {                                                                    │
│    echo '不合格';                                                          │
│}                                                                           │
└──────────────────────────────────────┘
これで、ほぼ十分なのだが、問題がある。
例えばよく使うパスワードの文字として「password」ってのがあるが
これは「5f4dcc3b5aa765d61d8327deb882cf99」に変換されるのだ。
(自分で変換してみればいい)
つまり「5f4dcc3b5aa765d61d8327deb882cf99」が流出すれば
元々「password」だったってことがわかってしまう。
この地道な作業を繰り返せば、機械的な変換表ができてしまう。

では、これにどう対策したらいいか。
つまりは、決まった変換が公になっているのが問題なのだ。

ということで、いたずらで私的な文字列を追加してあげればよい。
ハッシュ関数なのでちょっとした違いだけで、結果が大きく変わる。
こんな感じ。(「$適当な文字」には「1」とか「A」だけでもよい)
┌──────────────────────────────────────┐
│$平文 = 'パスワード';                                                       │
│$暗号文 = md5($平文 . $適当な文字);                                         │
├──────────────────────────────────────┤
│$入力文 = 'パスワード';                                                     │
│if (md5($入力文 . $適当な文字) == $暗号文) {                                │
│    echo '合格';                                                            │
│} else {                                                                    │
│    echo '不合格';                                                          │
│}                                                                           │
└──────────────────────────────────────┘
でも、問題がある。「$適当な文字」の管理が煩雑だ。
忘れると照合できなくなる一方、流出の恐れもある。
また、何をつかえばよいかも悩みどころだ。

ということで、これを簡単に実現してくれるのが「crypt()」だ。
┌──────────────────────────────────────┐
│$平文 = 'パスワード';                                                       │
│$暗号文 = crypt($平文);                                                     │
├──────────────────────────────────────┤
│$入力文 = 'パスワード';                                                     │
│if (crypt($入力文, $暗号文) == $暗号文) {                                   │
│    echo '合格';                                                            │
│} else {                                                                    │
│    echo '不合格';                                                          │
│}                                                                           │
└──────────────────────────────────────┘
「$適当な文字」的なところを、暗号文自身に付加してあげる感じ。
「crypt()」では、その「$適当な文字」的なところを抜き出して、
これを使って暗号化してくれるという仕組みだ。

なによりも「crypt($平文)」の部分は、実行する度に結果が変わる。
ハッシュを二重にかけているような感じだ。

ちなみに「crypt()」の「salt」は種別によって以下のような感じとなる。
┌───────┬──────────────────────────────┐
│CRYPT_STD_DES │xx                                                          │
├───────┼──────────────────────────────┤
│CRYPT_EXT_DES │_0000xxxx                                                   │
├───────┼──────────────────────────────┤
│CRYPT_MD5     │$1$xxxxxxxx$                                                │
├───────┼──────────────────────────────┤
│CRYPT_BLOWFISH│$2a$00$xxxxxxxxxxxxxxxxxxxxx                                │
│              │$2x$00$xxxxxxxxxxxxxxxxxxxxx                                │
│              │$2y$00$xxxxxxxxxxxxxxxxxxxxx                                │
├───────┼──────────────────────────────┤
│CRYPT_SHA256  │$5$xxxxxxxxxxxxxxxx                                         │
│              │$5$rounds=5000$xxxxxxxxxxxxxxxx                             │
├───────┼──────────────────────────────┤
│CRYPT_SHA512  │$6$xxxxxxxxxxxxxxxx                                         │
│              │$6$rounds=5000$xxxxxxxxxxxxxxxx                             │
└───────┴──────────────────────────────┘
分類:PHP