アカウント管理の続き。passwordの保存については前回書いた。emailの暗号化だが、mysqlのAES_ENCRYPT()関数とAES_DECRYPT関数を使えば良いらしい。MySQLのDocumentにも今のところ一番安全と書かれている。
MySQLに暗号化したデータを保存するには、BLOB型にしなければいけないと。そんなわけで、MySQLのテーブルは、以下のようになる。テーブル名はaccountにしよう。
- id int primary key auto_increment
- account varchar(128)
- p_hash varchar(256)
- email TINYBLOB
p_hashはpasswordの保存のところで作った、salt付きパスワードのハッシュを入れる。暗号化したemailはTINYBLOB型のemailに入れる。sha1のhash256バイトもないだろ。とか色々ツッコミどころはあるが、その辺は適当。TINYBLOBは256バイト。e-mailアドレスでそんなに長い奴いないし。後で逆算してe-mailアドレスの文字数制限でリミットかけないといけない。その上のBLOB型になると、65536バイトなのででかすぎ。
<?php class Account{ const SALT='awSEdrFTgyHUjiKOlp'; const CRYPT_KEY="AHAHAHA"; function registration($account,$password,$email) // password hashを作る $pwd_hash = sha1(self::SALT.$password); // sql queryを作る $sql = "INSERT INTO account (account,phash,email)". " VALUES('$account','$pwd_hash',AES_ENCRYPT('$email','".self::CRYPT_KEY."'))"; $db = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD); mysql_query($sql,$db); mysql_close($db); } } ?>
んで、暗号化するまでは良いとして、じゃぁ、引っ張ってくるときどうするの?。って話だ。
$sql="SELECT AEC_DECRYPT(email,'".self::CRYPT_KEY."') as email ". "FROM account WHERE account='$account'";
こんな感じで、復号化してあげる。
では、次にWHERE節で探す場合は?。
$sql="SELECT * FROM account ". "WHERE email=AES_ENCRYPT('$email','".self::CRYPT_KEY."')";
暗号化したものを探すので、AES_ENCRYPT()で暗号化して、比較してあげれば良いのね。
じゃ、次に、Likeとかはどうすんだ?。
$sql="SELECT * FROM account ". "WHERE AES_DECRYPT(email,'".self::CRYPT_KEY."')". " LIKE '%$keyword%'";
こう。今度は、復号化してからキーワードと比較しれあげれば良い。後は一緒でしょ。
mysql_fetch_xxとかは適当に。
ここで疑問、MySQLからデータが奪われてもe-mailは暗号化されているし、passwordも塩付きhashになってるから、まぁ大丈夫。でも・・。CRYPT_KEYがphpファイルに平文で書いてあるってどうなの?。phpのソースファイルは見られないって前提なのか?。と。そういわれりゃSSLの秘密鍵だってどっかのディレクトリの中にあるし、サーバーのフロントエンドがやられたら終わり。ということは、このCRYPT_KEYはSSLの秘密鍵のようにApacheの公開ディレクトリ以外のところに置いて、人から見られないようにしておくのがベターだよね。