暗号化する場合のmysqlのテーブル

アカウント管理の続き。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の公開ディレクトリ以外のところに置いて、人から見られないようにしておくのがベターだよね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)