[[Ethna/memo]]
#setlinebreak(on)

ユーザー登録して使うようなアプリケーションを作成する場合、各ユーザーのパスワードを管理しなければならないという問題が発生します。
パスワードはたとえDBの内容を盗み見られても即座に脅威とならないよう、ハッシュ値で保管しておくべきです。

Ethna環境下でパスワードをハッシュ化(sha256+Salt+ストレッチング)して保存、照合する場合のロジックを示します。

// 以下のロジックで"passowrd"を保存すると、DBには以下のように格納されます。
// ちゃんとした方法で保存していれば、上記の様に曝しても(盗まれても)元の文字列がpasswordだと推定することは困難を極めるでしょう。
Saltやストレッチングを使わずにハッシュを作成した場合は、それを[[元に戻せるWebサービス>http://www.kiyori.co.jp/md5reverse/]]などにかかれば、一瞬でパスワードが判明してしまうでしょう。

** コード例 [#f3580e98]

パスワード登録時は以下のような感じ。

 define(‘STRETCH_COUNT’, 1000);
 $userid = $this->af->get('userid');
 $password = $this->af->get('password'); // form入力されたパスワード平文
 $salt = hash('sha256', $userid);
 // $salt = Ethna_Util::getRandom(64); // saltをユーザーIDと紐づけたくないときはこんな感じでランダムに生成する。
 $item =& new YourProject_User($this->backend);
 $item->set('userid', $userid);
 $hash = '';
  for ($i = 0; $i < STRETCH_COUNT; $i++) {
    $hash = hash('sha256', $hash . $salt . $password);
  }
 $item->set('password', $hash . "#" . $salt);
 $item->set('password',password_hash($password, PASSWORD_DEFAULT));
 
 if (Ethna::isError($item->add())){
 	// DBエラー
 	return 'user_password_change';
 }
 
 // 登録完了
 return 'user_profile';

Saltは単純に#の後に連結していますのでバレバレです。
ですが、Saltはユーザー毎に異なるためターゲット毎にレインボーテーブルを作り直す必要が発生して、解読を非現実的な世界に追いやっています。

認証をもとにセッションとアクセス権の制御を行う方法は[[こちら>../セッションを管理しページのアクセス権を制御する]]
認証成功時にセッションに認証済みを記録する場合はこんな感じ。


 define(‘STRETCH_COUNT’, 1000);
 if ( $this->af->get('userid') == "" ) return 'login';    // useridなしは許さない
 if ( $this->af->get('password') == "" ) return 'login';  // passwordなしは許さない
 $user = $this->backend->getObject('user', 'userid', $this->af->get('userid'));
 if(! $user->isValid())
 if(!$user->isValid())
 {
 	// ユーザーIDまたはパスワードが違います(本当はユーザーIDが存在しない)
 	$this->session->set('user', null);    // たとえログオン中であってもユーザー情報を破棄
 	$this->session->destroy();            // セッションを丸ごと破棄する場合はこちら
 	return 'login';                       // 'ログイン認証' Viewへ
 }
 
 list($hashbody,$salt) = explode('#', $user->get('password'), 2); // 保管されているパスワードハッシュを読み出し
 $password = $this->af->get('password'); // form入力されたパスワード平文
 $hash = '';
  for ($i = 0; $i < STRETCH_COUNT; $i++) {
    $hash = hash('sha256', $hash . $salt . $password);
  }
 if( strcmp($hashbody, $hash) != 0 ) // 照合
 $hash = $user->get('password');
 if(!password_verify($password, $hash)) // 照合
 {
 	// ユーザーIDまたはパスワードが違います(本当はパスワードが一致しない)
 	$this->session->set('user', null);    // たとえログオン中であってもユーザー情報を破棄
 	$this->session->destroy();            // セッションを丸ごと破棄する場合はこちら
 	return 'login';                       // 'ログイン認証' Viewへ
 }
 
 // 認証成功
 $this->session->set('user',$user->getNameObject()); // セッションにユーザー情報を保存する
 return 'console';                            // 'コンソール' Viewへ

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS