最近の Linux などのユーザ認証は /etc/passwd,/etc/shadow ファイルで行われる。 たとえば
useradd hoge
と打ち込むと,/etc/passwd には
hoge:x:501:501::/home/hoge:/bin/bash
/etc/shadow には
hoge:!!:11940:0:99999:7:::
のように入る。 この段階ではまだログインできない。
次に,パスワードを設定する。
# passwd hoge Changing password for user hoge New UNIX password: hogehoge BAD PASSWORD: it does not contain enough DIFFERENT characters Retype new UNIX password: hogehoge passwd: all authentication tokens updated successfully
安易なパスワードなので途中で警告が出たが,スーパーユーザで行ったので設定できてしまった(後でちゃんと userdel hoge しておこう)。
/etc/shadow を見ると,次のように変更されている。
hoge:$1$wpkFeWyW$dRnpRo1XDyGJQkc1IM3CT1:11940:0:99999:7:::
この $1$wpkFeWyW$dRnpRo1XDyGJQkc1IM3CT1 の部分が MD5 アルゴリズムでハッシュされたパスワードである。 頭の $1$ は MD5 ハッシュであることの印である。 次の8文字 wpkFeWyW が salt(塩)と呼ばれるもので,a-zA-Z0-9./ の64通りの文字からランダムに選ばれる。 次の $ は区切りで,最後の22文字が salt とパスワードの組をハッシュした値をやはり a-zA-Z0-9./ の64通りの文字で表したものである。
この MD5 ハッシュを使うのは最近の方式で,昔は DES に基づく方式が使われていた。 一時的に DES 方式に戻してみよう。 Vine Linux 2.5 では /etc/pam.d/system-auth の
password sufficient /lib/security/pam_unix.so nullok use_authtok md5
という行の md5 を消せばよい。 もう一度パスワードを設定してみると,
hoge:EV7RndYXv5pHs:11941:0:99999:7:::
のようになった。 この場合,頭の2文字 EV が salt で,残り11文字 7RndYXv5pHs が salt とパスワードの組を DES で暗号化したものである。 a-zA-Z0-9./ の64通りの文字を使うという点では同じである。
DES を使った古い方式はパスワードの頭8文字の下位7ビットを合わせた56ビットしか使われないが,MD5 を使った新しい方式は長いパスワードを許すので,より安全である。
C言語を使って,パスワード設定・認証を自前でやってみよう。
いずれの方式についても,salt はパスワード設定時に a-zA-Z0-9./ の64通りの文字から乱数で選ぶ。
salt とパスワードから /etc/shadow のパスワード欄を生成するC言語の関数は crypt() である。 man crypt または info crypt で使い方を確認しよう。 MD5 を使うには glibc2 以降のライブラリが必要である。
#define _XOPEN_SOURCE #include <unistd.h> char *crypt(const char *key, const char *salt);
この #define _XOPEN_SOURCE はどの #include よりも前にないとうまくいかないことがある。
たとえば crypt("hogehoge", "$1$wpkFeWyW") とすると $1$wpkFeWyW$dRnpRo1XDyGJQkc1IM3CT1 が返り,crypt("hogehoge", "EV") とすると EV7RndYXv5pHs が返ることを確かめよう。
crypt() の第2引数は長すぎてもかまわない。 つまり,crypt("hogehoge", "EV7RndYXv5pHs:11941:0:99999:7:::") でもかまわない。 したがって,/etc/shadow の最初の : 以下すべてを渡せばよい。
サンプルソース auth.c を挙げておく。
Last modified: 2004-05-27 21:05:28