【PHP】パスワードリマインダと可逆暗号

パスワードリマインダってどうやって作るの・・?

といろいろ探して作り上げました。

まず、パスワードリマインダの仕組みについても
いろいろな考え方がありますね・・

パスワードリマインダーの実装を考える

まず、メールアドレスにパスワードを書いて送るというのはもちろんナイ。

メールアドレスにパスワード再設定用フォームへのリンクを貼るのができそうだなと。

上記サイトでは送付時に確認コードを表示して、再設定時に入力してもらうというのもあり、
ふむふむ確かにそれは理にかなっていると思いました。

パスワード再設定用フォームには、
暗号化したパラメータでユーザー識別情報を付けて送ろうと思いますが、
そのパラメータを故意に作ってアクセス出来てしまったらアウトです・・

まぁそこまで重要なデータを管理するわけではないのですが
サイトを作る以上、きちんと考えなくてはなりません。。
パラメータの内容を複雑(ここには書かないですが)にして、
パスワード再設定用フォームへのリンクを送付することにします。

そこでまずぶつかるのが暗号化。
可逆の。
(N師匠Special Thanks☆)
PHPではBlowfishとかmcrypt_genericあるようです。

PHPで暗号化・復号あれこれ がとっても為になりましたが、
これだけでは上手くいきませんでした。

PHP で復号可能な暗号化を行うときのまとめ にもありましたが、
コードが二つに分かれてしまうと $iv が別々の物になってしまうらしく
PHPの調べ物:暗号化-mcryptのサンプルコードのファンクションを参考にしたら達成できました☆

▼メール送付画面

if (!empty($userid) && !empty($input_mailadress)) {
// メールアドレスが登録されていることを確認してから送付
$query = “SELECT * FROM ユーザーマスタ WHERE userid = ‘$userid’ AND touroku_mailadress = ‘$input_mailadress'”;
$data = mysql_query($query, $db接続);

if (mysql_num_rows($data) == 1) {

// ★キーの作成と暗号化スタート

$keydata = “very_important_infomation_kokodaiji_time()moireru!“;
$base64_data = base64_encode($keydata);
$encrypted_data = encryptedData($base64_data, ‘ichiinospecialkeyword‘); (←ファンクション

$testkey = urlencode($encrypted_data);

$subject = ‘パスワードの再設定’;
$message = “$userid 様\n\n パスワード再設定用URLをお送り致します。\n\n
http://xxxxxxxxxx.com/sample.php?xxxid=” . $testkey . “;

//再設定メール送信
$mailfrom=”From:” .mb_encode_mimeheader(“事務局”) .”<test@test.com>”;
mb_language(“Ja”) ;
mb_internal_encoding(“UTF-8”);
mb_send_mail($input_mailadress, $subject, $message, $mailfrom);

echo ‘<strong>再設定用メールを送信しました。★時間以内に、メールでお送りしたリンクへアクセスしてパスワードを再設定してください</strong>’;

mysql_close($dbc);
exit();

}
else
{
echo ‘<strong>入力したメールアドレスは登録されていません。または、IDとの組み合わせが違います。</strong>’;
}

}
else {
echo ‘<p class=”error”>未入力箇所があります</p>’;
}

▼再設定画面

if(!empty($_GET[‘xxxid’]))
{
$xxxid = $_GET[‘xxxid’];

// 復号化
function decryptedData($input,$key)
{
$td = mcrypt_module_open(MCRYPT_TRIPLEDES,”,’cbc’,”);

// key(最大キー長に)
$ks = mcrypt_enc_get_key_size($td);
$key = substr(md5($key), 0, $ks);

// iv
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr(md5($key), 0, $ivsize);

mcrypt_generic_init($td, $key, $iv);
$decrypted_data = mdecrypt_generic($td, $input);

mcrypt_generic_deinit($td);
mcrypt_module_close($td);

//return $decrypted_data;
return rtrim($decrypted_data,”\0″);
}

$base64_decrypted_data = decryptedData($xxxid, ‘ichiinospecialkeyword‘);
$decrypted_data = base64_decode($base64_decrypted_data);

//受け取ったパラメータを戻して分解
$xxxids = explode(“/”, $decrypted_data);
list($userid, $userinfo, $senddata・・・) = $xxxids;

//パラメータの整合性チェック1
if(★★★)
{
echo “パラメータが不正です”;
mysql_close( );
exit();
}
else
{
  ~~

$query = “SELECT * FROM ユーザーマスタ WHERE userid = ‘$userid'”;
$data = mysql_query($query, $db接続);

//パラメータの整合性チェック2:ID
if (mysql_num_rows($data) == 1)
{
$row = mysql_fetch_assoc($data);

//パラメータの整合性チェック3:その他登録情報とかチェックできるものをいくつか
$touroku_info = $row[“touroku_info”];
if($userinfo == $touroku_info)
{
//パラメータ確認:有効期限
if ($senddata >= time()-99999)
{
echo “★時間以内のアクセス!!再設定処理開始~~”;
}
else
{
echo “再設定受付から★時間以上経過しました。もう一度パスワード再設定メールを発行し、★時間以内に再発行を完了してください。”;
mysql_close( );
exit();
}
}
else
{
echo “登録情報パラメータが不正です”;
mysql_close( );
exit();
}
}
else
{
echo “IDパラメータが不正です”;
mysql_close( );
exit();
}

}
}

———————-
URLに付けるには、
コードをURLencodeしたのですが、
GETで受け取ったらURLdecodeしなくても勝手にdecodeしてくれるようです^^

【☆2012/05/03追記】
使用しているファンクションのmcrypt関連について、
環境によってうまく作動しなかった・・

よく見るとある記号「/」が上手く変換できていなかった。
記号を変えるとうまくいきましたので
上手く行かなかったら文言の結合の接着部分に使う記号とかを変えて試してみるのもありかも。

—–

コメント

タイトルとURLをコピーしました